From d70eef21c87d36d5b33c6c33ae7c4e6074725c9a Mon Sep 17 00:00:00 2001 From: divyav-aot Date: Mon, 6 Nov 2023 12:41:08 -0500 Subject: [PATCH 001/238] ci/cd updated for rook --- .github/workflows/forms-flow-ai-web-cd.yml | 14 ++++++++++++++ .github/workflows/forms-flow-ai-web-ci.yml | 2 ++ .github/workflows/forms-flow-bpm-cd.yml | 14 ++++++++++++++ .github/workflows/forms-flow-web-cd.yml | 14 ++++++++++++++ .github/workflows/forms-flow-web-ci.yml | 2 ++ .github/workflows/notification-manager-cd.yml | 14 ++++++++++++++ .github/workflows/notification-manager-ci.yml | 2 ++ .github/workflows/request-management-api-cd.yml | 14 ++++++++++++++ .github/workflows/request-management-api-ci.yml | 4 +++- 9 files changed, 79 insertions(+), 1 deletion(-) diff --git a/.github/workflows/forms-flow-ai-web-cd.yml b/.github/workflows/forms-flow-ai-web-cd.yml index d51098f5f..a3b2e39b1 100644 --- a/.github/workflows/forms-flow-ai-web-cd.yml +++ b/.github/workflows/forms-flow-ai-web-cd.yml @@ -6,6 +6,8 @@ on: - dev - dev-marshal - test-marshal + - dev-rook + - test-rook - main paths: - "apps/forms-flow-ai/forms-flow-ai-web/**" @@ -47,6 +49,18 @@ jobs: echo "TAG_NAME="test"" >> $GITHUB_ENV echo "BRANCH_NAME="test-marshal"" >> $GITHUB_ENV echo "ENV_NAME="test"" >> $GITHUB_ENV + elif [ ${{ github.ref_name }} == 'dev-rook' ]; then + echo "For ${{ github.ref_name }} branch" + echo "TOOLS_NAME=${{secrets.OPENSHIFT4_AI_FRONTEND_REPOSITORY}}" >> $GITHUB_ENV + echo "TAG_NAME="dev"" >> $GITHUB_ENV + echo "BRANCH_NAME="dev-rook"" >> $GITHUB_ENV + echo "ENV_NAME="dev"" >> $GITHUB_ENV + elif [ ${{ github.ref_name }} == 'test-rook' ]; then + echo "For ${{ github.ref_name }} branch" + echo "TOOLS_NAME=${{secrets.OPENSHIFT4_AI_FRONTEND_REPOSITORY}}" >> $GITHUB_ENV + echo "TAG_NAME="test"" >> $GITHUB_ENV + echo "BRANCH_NAME="test-rook"" >> $GITHUB_ENV + echo "ENV_NAME="test"" >> $GITHUB_ENV elif [ ${{ github.ref_name }} == 'main' ]; then echo "For ${{ github.ref_name }} branch" echo "TOOLS_NAME=${{secrets.OPENSHIFT4_AI_FRONTEND_REPOSITORY}}" >> $GITHUB_ENV diff --git a/.github/workflows/forms-flow-ai-web-ci.yml b/.github/workflows/forms-flow-ai-web-ci.yml index dda8f9730..11eb07dfd 100644 --- a/.github/workflows/forms-flow-ai-web-ci.yml +++ b/.github/workflows/forms-flow-ai-web-ci.yml @@ -8,6 +8,8 @@ on: - main - dev-marshal - test-marshal + - dev-rook + - test-rook paths: - "apps/forms-flow-ai/forms-flow-ai-web/**" - "!apps/forms-flow-ai/forms-flow-ai-web/src/forms/**" diff --git a/.github/workflows/forms-flow-bpm-cd.yml b/.github/workflows/forms-flow-bpm-cd.yml index 32c68dea0..054f9a8f6 100644 --- a/.github/workflows/forms-flow-bpm-cd.yml +++ b/.github/workflows/forms-flow-bpm-cd.yml @@ -7,6 +7,8 @@ on: - dev - dev-marshal - test-marshal + - dev-rook + - test-rook - main paths: - "apps/forms-flow-ai/forms-flow-bpm/**" @@ -48,6 +50,18 @@ jobs: echo "TAG_NAME="test-marshal"" >> $GITHUB_ENV echo "BRANCH_NAME="test-marshal"" >> $GITHUB_ENV echo "ENV_NAME="test"" >> $GITHUB_ENV + elif [ ${{ github.ref_name }} == 'dev-rook' ]; then + echo "For ${{ github.ref_name }} branch" + echo "TOOLS_NAME=${{secrets.OPENSHIFT4_FRONTEND_REPOSITORY}}" >> $GITHUB_ENV + echo "TAG_NAME="dev-rook"" >> $GITHUB_ENV + echo "BRANCH_NAME="dev-rook"" >> $GITHUB_ENV + echo "ENV_NAME="dev"" >> $GITHUB_ENV + elif [ ${{ github.ref_name }} == 'test-rook' ]; then + echo "For ${{ github.ref_name }} branch" + echo "TOOLS_NAME=${{secrets.OPENSHIFT4_FRONTEND_REPOSITORY}}" >> $GITHUB_ENV + echo "TAG_NAME="test-rook"" >> $GITHUB_ENV + echo "BRANCH_NAME="test-rook"" >> $GITHUB_ENV + echo "ENV_NAME="test"" >> $GITHUB_ENV elif [ ${{ github.ref_name }} == 'main' ]; then echo "For ${{ github.ref_name }} branch" echo "TOOLS_NAME=${{secrets.OPENSHIFT4_FRONTEND_REPOSITORY}}" >> $GITHUB_ENV diff --git a/.github/workflows/forms-flow-web-cd.yml b/.github/workflows/forms-flow-web-cd.yml index f869dbf07..733624d41 100644 --- a/.github/workflows/forms-flow-web-cd.yml +++ b/.github/workflows/forms-flow-web-cd.yml @@ -7,6 +7,8 @@ on: - dev - dev-marshal - test-marshal + - dev-rook + - test-rook - main paths: - "forms-flow-web/**" @@ -47,6 +49,18 @@ jobs: echo "TAG_NAME="test-marshal"" >> $GITHUB_ENV echo "BRANCH_NAME="test-marshal"" >> $GITHUB_ENV echo "ENV_NAME="test"" >> $GITHUB_ENV + elif [ ${{ github.ref_name }} == 'dev-rook' ]; then + echo "For ${{ github.ref_name }} branch" + echo "TOOLS_NAME=${{secrets.OPENSHIFT4_FRONTEND_REPOSITORY}}" >> $GITHUB_ENV + echo "TAG_NAME="dev-rook"" >> $GITHUB_ENV + echo "BRANCH_NAME="dev-rook"" >> $GITHUB_ENV + echo "ENV_NAME="dev"" >> $GITHUB_ENV + elif [ ${{ github.ref_name }} == 'test-rook' ]; then + echo "For ${{ github.ref_name }} branch" + echo "TOOLS_NAME=${{secrets.OPENSHIFT4_FRONTEND_REPOSITORY}}" >> $GITHUB_ENV + echo "TAG_NAME="test-rook"" >> $GITHUB_ENV + echo "BRANCH_NAME="test-rook"" >> $GITHUB_ENV + echo "ENV_NAME="test"" >> $GITHUB_ENV elif [ ${{ github.ref_name }} == 'main' ]; then echo "For ${{ github.ref_name }} branch" echo "TOOLS_NAME=${{secrets.OPENSHIFT4_FRONTEND_REPOSITORY}}" >> $GITHUB_ENV diff --git a/.github/workflows/forms-flow-web-ci.yml b/.github/workflows/forms-flow-web-ci.yml index 1613bd2be..1ef259ca2 100644 --- a/.github/workflows/forms-flow-web-ci.yml +++ b/.github/workflows/forms-flow-web-ci.yml @@ -8,6 +8,8 @@ on: - dev - dev-marshal - test-marshal + - dev-rook + - test-rook paths: - "forms-flow-web/**" diff --git a/.github/workflows/notification-manager-cd.yml b/.github/workflows/notification-manager-cd.yml index 1a6db4426..c4daf23de 100644 --- a/.github/workflows/notification-manager-cd.yml +++ b/.github/workflows/notification-manager-cd.yml @@ -7,6 +7,8 @@ on: - dev - dev-marshal - test-marshal + - dev-rook + - test-rook - main paths: - "notification-manager/**" @@ -47,6 +49,18 @@ jobs: echo "TAG_NAME="test-marshal"" >> $GITHUB_ENV echo "BRANCH_NAME="test-marshal"" >> $GITHUB_ENV echo "ENV_NAME="test"" >> $GITHUB_ENV + elif [ ${{ github.ref_name }} == 'dev-rook' ]; then + echo "For ${{ github.ref_name }} branch" + echo "TOOLS_NAME=${{secrets.OPENSHIFT4_FRONTEND_REPOSITORY}}" >> $GITHUB_ENV + echo "TAG_NAME="dev-rook"" >> $GITHUB_ENV + echo "BRANCH_NAME="dev-rook"" >> $GITHUB_ENV + echo "ENV_NAME="dev"" >> $GITHUB_ENV + elif [ ${{ github.ref_name }} == 'test-rook' ]; then + echo "For ${{ github.ref_name }} branch" + echo "TOOLS_NAME=${{secrets.OPENSHIFT4_FRONTEND_REPOSITORY}}" >> $GITHUB_ENV + echo "TAG_NAME="test-rook"" >> $GITHUB_ENV + echo "BRANCH_NAME="test-rook"" >> $GITHUB_ENV + echo "ENV_NAME="test"" >> $GITHUB_ENV elif [ ${{ github.ref_name }} == 'main' ]; then echo "For ${{ github.ref_name }} branch" echo "TOOLS_NAME=${{secrets.OPENSHIFT4_FRONTEND_REPOSITORY}}" >> $GITHUB_ENV diff --git a/.github/workflows/notification-manager-ci.yml b/.github/workflows/notification-manager-ci.yml index 0b66bf390..1b3185813 100644 --- a/.github/workflows/notification-manager-ci.yml +++ b/.github/workflows/notification-manager-ci.yml @@ -8,6 +8,8 @@ on: - dev - dev-marshal - test-marshal + - dev-rook + - test-rook paths: - "notification-manager/**" diff --git a/.github/workflows/request-management-api-cd.yml b/.github/workflows/request-management-api-cd.yml index 0971ad928..908ec9a34 100644 --- a/.github/workflows/request-management-api-cd.yml +++ b/.github/workflows/request-management-api-cd.yml @@ -7,6 +7,8 @@ on: - dev - dev-marshal - test-marshal + - dev-rook + - test-rook - main paths: - "request-management-api/**" @@ -49,6 +51,18 @@ jobs: echo "TAG_NAME="test-marshal"" >> $GITHUB_ENV echo "BRANCH_NAME="test-marshal"" >> $GITHUB_ENV echo "ENV_NAME="test"" >> $GITHUB_ENV + elif [ ${{ github.ref_name }} == 'dev-rook' ]; then + echo "For ${{ github.ref_name }} branch" + echo "TOOLS_NAME=${{secrets.OPENSHIFT4_FRONTEND_REPOSITORY}}" >> $GITHUB_ENV + echo "TAG_NAME="dev-rook"" >> $GITHUB_ENV + echo "BRANCH_NAME="dev-rook"" >> $GITHUB_ENV + echo "ENV_NAME="dev"" >> $GITHUB_ENV + elif [ ${{ github.ref_name }} == 'test-rook' ]; then + echo "For ${{ github.ref_name }} branch" + echo "TOOLS_NAME=${{secrets.OPENSHIFT4_FRONTEND_REPOSITORY}}" >> $GITHUB_ENV + echo "TAG_NAME="test-rook"" >> $GITHUB_ENV + echo "BRANCH_NAME="test-rook"" >> $GITHUB_ENV + echo "ENV_NAME="test"" >> $GITHUB_ENV elif [ ${{ github.ref_name }} == 'main' ]; then echo "For ${{ github.ref_name }} branch" echo "TOOLS_NAME=${{secrets.OPENSHIFT4_FRONTEND_REPOSITORY}}" >> $GITHUB_ENV diff --git a/.github/workflows/request-management-api-ci.yml b/.github/workflows/request-management-api-ci.yml index 0055a4b1c..fd917c956 100644 --- a/.github/workflows/request-management-api-ci.yml +++ b/.github/workflows/request-management-api-ci.yml @@ -7,7 +7,9 @@ on: - main - dev - dev-marshal - - test-marshal + - test-marshal + - dev-rook + - test-rook paths: - "request-management-api/**" - "!request-management-api/request_api/email_templates/**" From cc48b1b1405a10bbb700a6dcce3b033ec1457d0b Mon Sep 17 00:00:00 2001 From: divyav-aot Date: Mon, 6 Nov 2023 12:49:51 -0500 Subject: [PATCH 002/238] updated the cd --- .github/workflows/forms-flow-bpm-cd.yml | 60 ++++++++++++++++--------- 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/.github/workflows/forms-flow-bpm-cd.yml b/.github/workflows/forms-flow-bpm-cd.yml index 054f9a8f6..4aed6db75 100644 --- a/.github/workflows/forms-flow-bpm-cd.yml +++ b/.github/workflows/forms-flow-bpm-cd.yml @@ -29,49 +29,65 @@ jobs: if: github.event_name == 'push' && github.repository == 'bcgov/foi-flow' steps: - uses: actions/checkout@v2 - - name: Set ENV variables - id: set-variable + - name: Set ENV variables for dev branch + if: ${{ github.ref_name == 'dev' }} + shell: bash run: | - if [ ${{ github.ref_name }} == 'dev' ]; then echo "For ${{ github.ref_name }} branch" echo "TOOLS_NAME=${{secrets.OPENSHIFT4_FRONTEND_REPOSITORY}}" >> $GITHUB_ENV echo "TAG_NAME="dev"" >> $GITHUB_ENV echo "BRANCH_NAME="dev"" >> $GITHUB_ENV echo "ENV_NAME="dev"" >> $GITHUB_ENV - elif [ ${{ github.ref_name }} == 'dev-marshal' ]; then - echo "For ${{ github.ref_name }} branch" - echo "TOOLS_NAME=${{secrets.OPENSHIFT4_FRONTEND_REPOSITORY}}" >> $GITHUB_ENV - echo "TAG_NAME="dev-marshal"" >> $GITHUB_ENV - echo "BRANCH_NAME="dev-marshal"" >> $GITHUB_ENV - echo "ENV_NAME="dev"" >> $GITHUB_ENV - elif [ ${{ github.ref_name }} == 'test-marshal' ]; then - echo "For ${{ github.ref_name }} branch" - echo "TOOLS_NAME=${{secrets.OPENSHIFT4_FRONTEND_REPOSITORY}}" >> $GITHUB_ENV - echo "TAG_NAME="test-marshal"" >> $GITHUB_ENV - echo "BRANCH_NAME="test-marshal"" >> $GITHUB_ENV - echo "ENV_NAME="test"" >> $GITHUB_ENV - elif [ ${{ github.ref_name }} == 'dev-rook' ]; then + + - name: Set ENV variables for dev-marshal branch + if: ${{ github.ref_name == 'dev-marshal' }} + shell: bash + run: | + echo "For ${{ github.ref_name }} branch" + echo "TOOLS_NAME=${{secrets.OPENSHIFT4_FRONTEND_REPOSITORY}}" >> $GITHUB_ENV + echo "TAG_NAME="dev-marshal"" >> $GITHUB_ENV + echo "BRANCH_NAME="dev-marshal"" >> $GITHUB_ENV + echo "ENV_NAME="dev"" >> $GITHUB_ENV + + - name: Set ENV variables for test-marshal branch + if: ${{ github.ref_name == 'test-marshal' }} + shell: bash + run: | + echo "For ${{ github.ref_name }} branch" + echo "TOOLS_NAME=${{secrets.OPENSHIFT4_FRONTEND_REPOSITORY}}" >> $GITHUB_ENV + echo "TAG_NAME="test-marshal"" >> $GITHUB_ENV + echo "BRANCH_NAME="test-marshal"" >> $GITHUB_ENV + echo "ENV_NAME="test"" >> $GITHUB_ENV + + - name: Set ENV variables for dev-rook branch + if: ${{ github.ref_name == 'dev-rook' }} + shell: bash + run: | echo "For ${{ github.ref_name }} branch" echo "TOOLS_NAME=${{secrets.OPENSHIFT4_FRONTEND_REPOSITORY}}" >> $GITHUB_ENV echo "TAG_NAME="dev-rook"" >> $GITHUB_ENV echo "BRANCH_NAME="dev-rook"" >> $GITHUB_ENV echo "ENV_NAME="dev"" >> $GITHUB_ENV - elif [ ${{ github.ref_name }} == 'test-rook' ]; then + + - name: Set ENV variables for test-rook branch + if: ${{ github.ref_name == 'test-rook' }} + shell: bash + run: | echo "For ${{ github.ref_name }} branch" echo "TOOLS_NAME=${{secrets.OPENSHIFT4_FRONTEND_REPOSITORY}}" >> $GITHUB_ENV echo "TAG_NAME="test-rook"" >> $GITHUB_ENV echo "BRANCH_NAME="test-rook"" >> $GITHUB_ENV echo "ENV_NAME="test"" >> $GITHUB_ENV - elif [ ${{ github.ref_name }} == 'main' ]; then + + - name: Set ENV variables for main branch + if: ${{ github.ref_name == 'main' }} + shell: bash + run: | echo "For ${{ github.ref_name }} branch" echo "TOOLS_NAME=${{secrets.OPENSHIFT4_FRONTEND_REPOSITORY}}" >> $GITHUB_ENV echo "TAG_NAME="test"" >> $GITHUB_ENV echo "BRANCH_NAME="main"" >> $GITHUB_ENV echo "ENV_NAME="test"" >> $GITHUB_ENV - else - echo "For ${{ github.ref_name }} branch" - fi - shell: bash - name: Login Openshift shell: bash From b7152d98eaa168d91f1465a01ce850e871a64256 Mon Sep 17 00:00:00 2001 From: divyav-aot Date: Fri, 10 Nov 2023 12:39:22 -0500 Subject: [PATCH 003/238] moved unSavedRequest state variable declaration to the top --- .../MinistryReview/MinistryReview.js | 54 ++++++++++++------- 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js index 0b387c410..91614c5b2 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js @@ -17,7 +17,7 @@ import { import { fetchFOIMinistryAssignedToList, - fetchFOIPersonalDivisionsAndSections + fetchFOIPersonalDivisionsAndSections, } from "../../../../apiManager/services/FOI/foiMasterDataServices"; import { fetchFOIRequestAttachmentsList } from "../../../../apiManager/services/FOI/foiAttachmentServices"; @@ -227,7 +227,12 @@ const MinistryReview = React.memo(({ userDetail }) => { const [originalDivisions, setOriginalDivisions] = React.useState([]); const [hasReceivedDate, setHasReceivedDate] = React.useState(true); const [isMinistryRestricted, setIsMinistryRestricted] = useState(false); - const [isMCFPersonal, setIsMCFPersonal] = useState(bcgovcode.replaceAll('"', '') == "MCF" && requestDetails.requestType == FOI_COMPONENT_CONSTANTS.REQUEST_TYPE_PERSONAL); + const [isMCFPersonal, setIsMCFPersonal] = useState( + bcgovcode.replaceAll('"', "") == "MCF" && + requestDetails.requestType == + FOI_COMPONENT_CONSTANTS.REQUEST_TYPE_PERSONAL + ); + const [unSavedRequest, setUnSavedRequest] = React.useState(false); let ministryassignedtousername = "Unassigned"; useEffect(() => { @@ -249,9 +254,15 @@ const MinistryReview = React.memo(({ userDetail }) => { ); } - if(MinistryNeedsScanning.includes(bcgovcode.replaceAll('"', '')) && requestDetails.requestType == FOI_COMPONENT_CONSTANTS.REQUEST_TYPE_PERSONAL) { - dispatch(fetchFOIPersonalDivisionsAndSections(bcgovcode.replaceAll('"', ''))); - if(bcgovcode.replaceAll('"', '') == "MCF") { + if ( + MinistryNeedsScanning.includes(bcgovcode.replaceAll('"', "")) && + requestDetails.requestType == + FOI_COMPONENT_CONSTANTS.REQUEST_TYPE_PERSONAL + ) { + dispatch( + fetchFOIPersonalDivisionsAndSections(bcgovcode.replaceAll('"', "")) + ); + if (bcgovcode.replaceAll('"', "") == "MCF") { setIsMCFPersonal(true); } } @@ -269,7 +280,6 @@ const MinistryReview = React.memo(({ userDetail }) => { } }, [isMinistryRestricted, requestWatchers]); - const [unSavedRequest, setUnSavedRequest] = React.useState(false); const [recordsUploading, setRecordsUploading] = React.useState(false); const [CFRUnsaved, setCFRUnsaved] = React.useState(false); const hideBottomText = [ @@ -426,11 +436,11 @@ const MinistryReview = React.memo(({ userDetail }) => { foitabheaderBG = "foitabheadercollection foitabheaderPeerreviewBG"; break; case StateEnum.tagging.name: - foitabheaderBG = "foitabheadercollection foitabheaderTaggingBG"; - break; + foitabheaderBG = "foitabheadercollection foitabheaderTaggingBG"; + break; case StateEnum.readytoscan.name: - foitabheaderBG = "foitabheadercollection foitabheaderReadytoScanBG"; - break; + foitabheaderBG = "foitabheadercollection foitabheaderReadytoScanBG"; + break; default: foitabheaderBG = "foitabheadercollection foitabheaderdefaultBG"; break; @@ -632,15 +642,18 @@ const MinistryReview = React.memo(({ userDetail }) => { ? `(${requestNotes.length})` : ""} - {(originalDivisions?.length > 0 || isMCFPersonal) && DISABLE_GATHERINGRECORDS_TAB?.toLowerCase() =='false' &&
tabclick("Records")} - > - Records -
} + {(originalDivisions?.length > 0 || isMCFPersonal) && + DISABLE_GATHERINGRECORDS_TAB?.toLowerCase() == "false" && ( +
tabclick("Records")} + > + Records +
+ )}
@@ -938,7 +951,8 @@ const MinistryReview = React.memo(({ userDetail }) => { [classes.hidden]: !tabLinksStatuses.Records.display, })} > - {!isAttachmentListLoading && (originalDivisions?.length > 0 || isMCFPersonal) ? ( + {!isAttachmentListLoading && + (originalDivisions?.length > 0 || isMCFPersonal) ? ( <> {url.indexOf("records") > -1 ? ( Date: Tue, 14 Nov 2023 22:56:02 -0800 Subject: [PATCH 004/238] Create migration file for OIPC tables --- .../3b399ca506fe_create_oipc_tables.py | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 request-management-api/migrations/versions/3b399ca506fe_create_oipc_tables.py diff --git a/request-management-api/migrations/versions/3b399ca506fe_create_oipc_tables.py b/request-management-api/migrations/versions/3b399ca506fe_create_oipc_tables.py new file mode 100644 index 000000000..549d04ade --- /dev/null +++ b/request-management-api/migrations/versions/3b399ca506fe_create_oipc_tables.py @@ -0,0 +1,75 @@ +"""Create OIPC tables + +Revision ID: 3b399ca506fe +Revises: 7fa7236d06fb +Create Date: 2023-11-14 22:29:58.451320 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql +from sqlalchemy import Table, Column, Integer, String, MetaData +meta = MetaData() + + +# revision identifiers, used by Alembic. +revision = '3b399ca506fe' +down_revision = '7fa7236d06fb' +branch_labels = None +depends_on = None + + +def upgrade(): + subjectcodestable = op.create_table('OIPCReviewTypes', + sa.Column('reviewtypeid', sa.Integer(), autoincrement=True, nullable=False), + sa.Column('created_at', sa.DateTime(), nullable=True), + sa.Column('createdby', sa.String(length=120), nullable=True), + sa.Column('updated_at', sa.DateTime(), nullable=True), + sa.Column('updatedby', sa.String(length=120), nullable=True), + sa.Column('isactive', sa.Boolean(), nullable=False), + sa.PrimaryKeyConstraint('reviewtypeid') + ) + + reasonstable = op.create_table('OIPCReasons', + sa.Column('reasonid', sa.Integer(), autoincrement=True, nullable=False), + sa.Column('created_at', sa.DateTime(), nullable=True), + sa.Column('createdby', sa.String(length=120), nullable=True), + sa.Column('updated_at', sa.DateTime(), nullable=True), + sa.Column('updatedby', sa.String(length=120), nullable=True), + sa.Column('isactive', sa.Boolean(), nullable=False), + sa.PrimaryKeyConstraint('reasonid') + ) + + statusestable = op.create_table('OIPCStatuses', + sa.Column('statusid', sa.Integer(), autoincrement=True, nullable=False), + sa.Column('created_at', sa.DateTime(), nullable=True), + sa.Column('createdby', sa.String(length=120), nullable=True), + sa.Column('updated_at', sa.DateTime(), nullable=True), + sa.Column('updatedby', sa.String(length=120), nullable=True), + sa.Column('isactive', sa.Boolean(), nullable=False), + sa.PrimaryKeyConstraint('statusid') + ) + + outcomestable = op.create_table('OIPCOutcomes', + sa.Column('outcomeid', sa.Integer(), autoincrement=True, nullable=False), + sa.Column('created_at', sa.DateTime(), nullable=True), + sa.Column('createdby', sa.String(length=120), nullable=True), + sa.Column('updated_at', sa.DateTime(), nullable=True), + sa.Column('updatedby', sa.String(length=120), nullable=True), + sa.Column('isactive', sa.Boolean(), nullable=False), + sa.PrimaryKeyConstraint('outcomeid') + ) + # op.execute('''CREATE TABLE OIPCReviewTypes ( + # reviewtypeid integer PRIMARY KEY, + # created_at datetime, + # created_by varchar(120), + # updated_at datetime, + # updated_by varchar(120), + # isactive boolean NOT NULL + # )''') + +def downgrade(): + op.drop_table('OIPCReviewTypes') + op.drop_table('OIPCReasons') + op.drop_table('OIPCStatuses') + op.drop_table('OIPCOutcomes') From 92e416b92498e9032370597eab6c725f1f9b2ace Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Wed, 15 Nov 2023 12:24:12 -0800 Subject: [PATCH 005/238] Update migration file --- .../3b399ca506fe_create_oipc_tables.py | 92 +++++++++++++------ 1 file changed, 63 insertions(+), 29 deletions(-) diff --git a/request-management-api/migrations/versions/3b399ca506fe_create_oipc_tables.py b/request-management-api/migrations/versions/3b399ca506fe_create_oipc_tables.py index 549d04ade..c4f22eccb 100644 --- a/request-management-api/migrations/versions/3b399ca506fe_create_oipc_tables.py +++ b/request-management-api/migrations/versions/3b399ca506fe_create_oipc_tables.py @@ -20,56 +20,90 @@ def upgrade(): - subjectcodestable = op.create_table('OIPCReviewTypes', + reviewtypestable = op.create_table('OIPCReviewTypes', sa.Column('reviewtypeid', sa.Integer(), autoincrement=True, nullable=False), - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('createdby', sa.String(length=120), nullable=True), - sa.Column('updated_at', sa.DateTime(), nullable=True), - sa.Column('updatedby', sa.String(length=120), nullable=True), - sa.Column('isactive', sa.Boolean(), nullable=False), + sa.Column('name', sa.String(length=100), unique=False, nullable=False), + sa.Column('isactive', sa.Boolean(), unique=False, nullable=False), sa.PrimaryKeyConstraint('reviewtypeid') ) reasonstable = op.create_table('OIPCReasons', sa.Column('reasonid', sa.Integer(), autoincrement=True, nullable=False), - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('createdby', sa.String(length=120), nullable=True), - sa.Column('updated_at', sa.DateTime(), nullable=True), - sa.Column('updatedby', sa.String(length=120), nullable=True), - sa.Column('isactive', sa.Boolean(), nullable=False), + sa.Column('name', sa.String(length=100), unique=False, nullable=False), + sa.Column('isactive', sa.Boolean(), unique=False, nullable=False), sa.PrimaryKeyConstraint('reasonid') ) statusestable = op.create_table('OIPCStatuses', sa.Column('statusid', sa.Integer(), autoincrement=True, nullable=False), - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('createdby', sa.String(length=120), nullable=True), - sa.Column('updated_at', sa.DateTime(), nullable=True), - sa.Column('updatedby', sa.String(length=120), nullable=True), - sa.Column('isactive', sa.Boolean(), nullable=False), + sa.Column('name', sa.String(length=100), unique=False, nullable=False), + sa.Column('isactive', sa.Boolean(), unique=False, nullable=False), sa.PrimaryKeyConstraint('statusid') ) outcomestable = op.create_table('OIPCOutcomes', sa.Column('outcomeid', sa.Integer(), autoincrement=True, nullable=False), - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('createdby', sa.String(length=120), nullable=True), - sa.Column('updated_at', sa.DateTime(), nullable=True), - sa.Column('updatedby', sa.String(length=120), nullable=True), - sa.Column('isactive', sa.Boolean(), nullable=False), + sa.Column('name', sa.String(length=100), unique=False, nullable=False), + sa.Column('isactive', sa.Boolean(), unique=False, nullable=False), sa.PrimaryKeyConstraint('outcomeid') ) - # op.execute('''CREATE TABLE OIPCReviewTypes ( - # reviewtypeid integer PRIMARY KEY, - # created_at datetime, - # created_by varchar(120), - # updated_at datetime, - # updated_by varchar(120), - # isactive boolean NOT NULL - # )''') + + inquiryoutcomestable = op.create_table('OIPCInquiryOutcomes', + sa.Column('inquiryoutcomeid', sa.Integer(), autoincrement=True, nullable=False), + sa.Column('name', sa.String(length=100), unique=False, nullable=False), + sa.Column('isactive', sa.Boolean(), unique=False, nullable=False), + sa.PrimaryKeyConstraint('inquiryoutcomeid') + ) + + op.execute('''INSERT INTO public."OIPCReviewTypes" (name, isactive) + VALUES + ('Complaint', True), + ('Review', True), + ('Investigation', True);commit;''') + + op.execute('''INSERT INTO public."OIPCReasons" (name, isactive) + VALUES + ('Adequate Search', True), + ('Application of Exceptions', True), + ('Deemed Refusal', True), + ('Extension', True), + ('Fee Amount', True), + ('Fee Waiver', True), + ('Records do not Exist', True), + ('Duty to Assist', True), + ('TPN - 22', True), + ('TPN - 21', True), + ('TPN - 18.1', True), + ('Reg 3', True), + ('Reg 4', True), + ('Reg 5', True), + ('s. 43', True), + ('Other', True);commit;''') + + op.execute('''INSERT INTO public."OIPCStatuses" (name, isactive) + VALUES + ('Mediation', True), + ('Investigation', True), + ('Inquiry', True), + ('Awaiting Order', True), + ('Closed', True);commit;''') + + op.execute('''INSERT INTO public."OIPCOutcomes" (name, isactive) + VALUES + ('Abandoned', True), + ('Withdrawn', True), + ('Resolved in Mediation', True), + ('Closed', True);commit;''') + + op.execute('''INSERT INTO public."OIPCInquiryOutcomes" (name, isactive) + VALUES + ('Decision Upheld', True), + ('Decision Partially Upheld', True), + ('Decision Overturned', True);commit;''') def downgrade(): op.drop_table('OIPCReviewTypes') op.drop_table('OIPCReasons') op.drop_table('OIPCStatuses') op.drop_table('OIPCOutcomes') + op.drop_table('OIPCInquiryOutcomes') From 0b4cdd1417ebdd9be4f1690ac2dc27c7bfd1095b Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Wed, 15 Nov 2023 12:25:33 -0800 Subject: [PATCH 006/238] Create endpoints for OIPC data --- .../resources/foiflowmasterdata.py | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/request-management-api/request_api/resources/foiflowmasterdata.py b/request-management-api/request_api/resources/foiflowmasterdata.py index 6525eef82..2d75d602c 100644 --- a/request-management-api/request_api/resources/foiflowmasterdata.py +++ b/request-management-api/request_api/resources/foiflowmasterdata.py @@ -33,6 +33,7 @@ from request_api.services.extensionreasonservice import extensionreasonservice from request_api.services.cacheservice import cacheservice from request_api.services.subjectcodeservice import subjectcodeservice +from request_api.services.oipcservice import oipcservice import json import request_api import requests @@ -380,3 +381,113 @@ def post(): return {"success": resp_flag } , 200 if resp_flag == True else 500 except BusinessException: return "Error happened while clearing cache" , 500 + +@cors_preflight('GET,OPTIONS') +@API.route('/foiflow/oipc/reviewtypes') +class FOIFlowOIPCReviewTypes(Resource): + """Retrieves OIPC review types + """ + @staticmethod + @TRACER.trace() + @cross_origin(origins=allowedorigins()) + # @auth.require + @request_api.cache.cached( + key_prefix="oipcreviewtypes", + unless=cache_filter, + response_filter=response_filter + ) + def get(): + try: + data = oipcservice().getreviewtypes() + jsondata = json.dumps(data) + return jsondata , 200 + except BusinessException: + return "Error happened while accessing OIPC review types" , 500 + +@cors_preflight('GET,OPTIONS') +@API.route('/foiflow/oipc/statuses') +class FOIFlowOIPCStatuses(Resource): + """Retrieves OIPC statuses + """ + @staticmethod + @TRACER.trace() + @cross_origin(origins=allowedorigins()) + # @auth.require + @request_api.cache.cached( + key_prefix="oipcstatuses", + unless=cache_filter, + response_filter=response_filter + ) + def get(): + try: + data = oipcservice().getstatuses() + jsondata = json.dumps(data) + return jsondata , 200 + except BusinessException: + return "Error happened while accessing OIPC statuses" , 500 + +@cors_preflight('GET,OPTIONS') +@API.route('/foiflow/oipc/reasons') +class FOIFlowOIPCReasons(Resource): + """Retrieves OIPC reasons + """ + @staticmethod + @TRACER.trace() + @cross_origin(origins=allowedorigins()) + # @auth.require + @request_api.cache.cached( + key_prefix="oipcreasons", + unless=cache_filter, + response_filter=response_filter + ) + def get(): + try: + data = oipcservice().getreasons() + jsondata = json.dumps(data) + return jsondata , 200 + except BusinessException: + return "Error happened while accessing OIPC reasons" , 500 + +@cors_preflight('GET,OPTIONS') +@API.route('/foiflow/oipc/outcomes') +class FOIFlowOIPCOutcomes(Resource): + """Retrieves OIPC outcomes + """ + @staticmethod + @TRACER.trace() + @cross_origin(origins=allowedorigins()) + # @auth.require + @request_api.cache.cached( + key_prefix="oipcoutcomes", + unless=cache_filter, + response_filter=response_filter + ) + def get(): + try: + data = oipcservice().getoutcomes() + jsondata = json.dumps(data) + return jsondata , 200 + except BusinessException: + return "Error happened while accessing OIPC outcomes" , 500 + +@cors_preflight('GET,OPTIONS') +@API.route('/foiflow/oipc/inquiryoutcomes') +class FOIFlowOIPCInquiryOutcomes(Resource): + """Retrieves OIPC inquiry outcomes + """ + @staticmethod + @TRACER.trace() + @cross_origin(origins=allowedorigins()) + # @auth.require + @request_api.cache.cached( + key_prefix="oipcinquiryoutcomes", + unless=cache_filter, + response_filter=response_filter + ) + def get(): + try: + data = oipcservice().getinquiryoutcomes() + jsondata = json.dumps(data) + return jsondata , 200 + except BusinessException: + return "Error happened while accessing OIPC inquiry outcomes" , 500 \ No newline at end of file From 7fd77828e540fc2d0bc4028b155285354b6f70d7 Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Wed, 15 Nov 2023 12:26:12 -0800 Subject: [PATCH 007/238] Create OIPC models and service --- .../request_api/models/OIPCInquiryOutcomes.py | 19 +++++++++++++++ .../request_api/models/OIPCOutcomes.py | 19 +++++++++++++++ .../request_api/models/OIPCReasons.py | 20 ++++++++++++++++ .../request_api/models/OIPCReviewTypes.py | 19 +++++++++++++++ .../request_api/models/OIPCStatuses.py | 19 +++++++++++++++ .../request_api/services/oipcservice.py | 23 +++++++++++++++++++ 6 files changed, 119 insertions(+) create mode 100644 request-management-api/request_api/models/OIPCInquiryOutcomes.py create mode 100644 request-management-api/request_api/models/OIPCOutcomes.py create mode 100644 request-management-api/request_api/models/OIPCReasons.py create mode 100644 request-management-api/request_api/models/OIPCReviewTypes.py create mode 100644 request-management-api/request_api/models/OIPCStatuses.py create mode 100644 request-management-api/request_api/services/oipcservice.py diff --git a/request-management-api/request_api/models/OIPCInquiryOutcomes.py b/request-management-api/request_api/models/OIPCInquiryOutcomes.py new file mode 100644 index 000000000..a613f0a7f --- /dev/null +++ b/request-management-api/request_api/models/OIPCInquiryOutcomes.py @@ -0,0 +1,19 @@ +from .db import db, ma + +class OIPCInquiryOutcomes(db.Model): + __tablename__ = 'OIPCInquiryOutcomes' + # Defining the columns + inquiryoutcomeid = db.Column(db.Integer, primary_key=True,autoincrement=True) + name = db.Column(db.String(100), unique=False, nullable=False) + isactive = db.Column(db.Boolean, unique=False, nullable=False) + + @classmethod + def getinquiryoutcomes(cls): + type_schema = InquiryOutcomeSchema(many=True) + query = db.session.query(OIPCInquiryOutcomes).filter_by(isactive=True).all() + return type_schema.dump(query) + + +class InquiryOutcomeSchema(ma.Schema): + class Meta: + fields = ('inquiryoutcomeid', 'name','isactive') \ No newline at end of file diff --git a/request-management-api/request_api/models/OIPCOutcomes.py b/request-management-api/request_api/models/OIPCOutcomes.py new file mode 100644 index 000000000..c891a88a8 --- /dev/null +++ b/request-management-api/request_api/models/OIPCOutcomes.py @@ -0,0 +1,19 @@ +from .db import db, ma + +class OIPCOutcomes(db.Model): + __tablename__ = 'OIPCOutcomes' + # Defining the columns + outcomeid = db.Column(db.Integer, primary_key=True,autoincrement=True) + name = db.Column(db.String(100), unique=False, nullable=False) + isactive = db.Column(db.Boolean, unique=False, nullable=False) + + @classmethod + def getoutcomes(cls): + type_schema = OutcomeSchema(many=True) + query = db.session.query(OIPCOutcomes).filter_by(isactive=True).all() + return type_schema.dump(query) + + +class OutcomeSchema(ma.Schema): + class Meta: + fields = ('outcomeid', 'name','isactive') \ No newline at end of file diff --git a/request-management-api/request_api/models/OIPCReasons.py b/request-management-api/request_api/models/OIPCReasons.py new file mode 100644 index 000000000..6eadc03b6 --- /dev/null +++ b/request-management-api/request_api/models/OIPCReasons.py @@ -0,0 +1,20 @@ + +from .db import db, ma + +class OIPCReasons(db.Model): + __tablename__ = 'OIPCReasons' + # Defining the columns + reasonid = db.Column(db.Integer, primary_key=True,autoincrement=True) + name = db.Column(db.String(100), unique=False, nullable=False) + isactive = db.Column(db.Boolean, unique=False, nullable=False) + + @classmethod + def getreasons(cls): + type_schema = ReasonSchema(many=True) + query = db.session.query(OIPCReasons).filter_by(isactive=True).all() + return type_schema.dump(query) + + +class ReasonSchema(ma.Schema): + class Meta: + fields = ('reasonid', 'name','isactive') \ No newline at end of file diff --git a/request-management-api/request_api/models/OIPCReviewTypes.py b/request-management-api/request_api/models/OIPCReviewTypes.py new file mode 100644 index 000000000..bb5317de8 --- /dev/null +++ b/request-management-api/request_api/models/OIPCReviewTypes.py @@ -0,0 +1,19 @@ +from .db import db, ma + +class OIPCReviewTypes(db.Model): + __tablename__ = 'OIPCReviewTypes' + # Defining the columns + reviewtypeid = db.Column(db.Integer, primary_key=True,autoincrement=True) + name = db.Column(db.String(100), unique=False, nullable=False) + isactive = db.Column(db.Boolean, unique=False, nullable=False) + + @classmethod + def getreviewtypes(cls): + type_schema = ReviewTypeSchema(many=True) + query = db.session.query(OIPCReviewTypes).filter_by(isactive=True).all() + return type_schema.dump(query) + + +class ReviewTypeSchema(ma.Schema): + class Meta: + fields = ('reviewtypeid', 'name','isactive') \ No newline at end of file diff --git a/request-management-api/request_api/models/OIPCStatuses.py b/request-management-api/request_api/models/OIPCStatuses.py new file mode 100644 index 000000000..dce07aac2 --- /dev/null +++ b/request-management-api/request_api/models/OIPCStatuses.py @@ -0,0 +1,19 @@ +from .db import db, ma + +class OIPCStatuses(db.Model): + __tablename__ = 'OIPCStatuses' + # Defining the columns + statusid = db.Column(db.Integer, primary_key=True,autoincrement=True) + name = db.Column(db.String(100), unique=False, nullable=False) + isactive = db.Column(db.Boolean, unique=False, nullable=False) + + @classmethod + def getstatuses(cls): + type_schema = StatusSchema(many=True) + query = db.session.query(OIPCStatuses).filter_by(isactive=True).all() + return type_schema.dump(query) + + +class StatusSchema(ma.Schema): + class Meta: + fields = ('statusid', 'name','isactive') \ No newline at end of file diff --git a/request-management-api/request_api/services/oipcservice.py b/request-management-api/request_api/services/oipcservice.py new file mode 100644 index 000000000..2ea4719f8 --- /dev/null +++ b/request-management-api/request_api/services/oipcservice.py @@ -0,0 +1,23 @@ +from request_api.models.OIPCReviewTypes import OIPCReviewTypes +from request_api.models.OIPCStatuses import OIPCStatuses +from request_api.models.OIPCReasons import OIPCReasons +from request_api.models.OIPCOutcomes import OIPCOutcomes +from request_api.models.OIPCInquiryOutcomes import OIPCInquiryOutcomes + +class oipcservice: + """ OIPC service + """ + def getreviewtypes(self): + return OIPCReviewTypes.getreviewtypes() + + def getreasons(self): + return OIPCReasons.getreasons() + + def getstatuses(self): + return OIPCStatuses.getstatuses() + + def getoutcomes(self): + return OIPCOutcomes.getoutcomes() + + def getinquiryoutcomes(self): + return OIPCInquiryOutcomes.getinquiryoutcomes() \ No newline at end of file From 7de09918acd0c02a986b1df6d1f837f4a03c82ae Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Wed, 15 Nov 2023 13:32:52 -0800 Subject: [PATCH 008/238] Initial commit / setup --- .../components/FOI/FOIRequest/FOIRequest.js | 5 ++ .../FOIRequest/OIPCDetails/AddOIPCButton.jsx | 0 .../OIPCDetails/AdditionalFields.jsx | 0 .../OIPCDetails/AdditionalInquiryFields.jsx | 0 .../FOI/FOIRequest/OIPCDetails/Index.jsx | 51 +++++++++++++++++++ .../OIPCDetails/MandatoryFields.jsx | 0 .../OIPCDetails/OIPCDetailsList.jsx | 14 +++++ .../FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 0 .../FOIRequest/OIPCDetails/oipcdetails.scss | 34 +++++++++++++ 9 files changed, 104 insertions(+) create mode 100644 forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/AddOIPCButton.jsx create mode 100644 forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/AdditionalFields.jsx create mode 100644 forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/AdditionalInquiryFields.jsx create mode 100644 forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx create mode 100644 forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/MandatoryFields.jsx create mode 100644 forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx create mode 100644 forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx create mode 100644 forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcdetails.scss diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index d754731d2..26a40787d 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -89,6 +89,7 @@ import { UnsavedModal } from "../customComponents"; import { DISABLE_GATHERINGRECORDS_TAB } from "../../../constants/constants"; import _ from "lodash"; import { MinistryNeedsScanning } from "../../../constants/FOI/enum"; +import OIPCDetails from "./OIPCDetails/Index"; const useStyles = makeStyles((theme) => ({ root: { @@ -251,6 +252,7 @@ const FOIRequest = React.memo(({ userDetail }) => { const [isIAORestricted, setIsIAORestricted] = useState(false); const [redactedSections, setRedactedSections] = useState(""); const [isMCFPersonal, setIsMCFPersonal] = useState(bcgovcode.replaceAll('"', '') == "MCF" && requestDetails.requestType == FOI_COMPONENT_CONSTANTS.REQUEST_TYPE_PERSONAL); + const [showOIPCDetails, setShowOIPCDetails] = useState(true); useEffect(() => { if (window.location.href.indexOf("comments") > -1) { @@ -1207,6 +1209,9 @@ const FOIRequest = React.memo(({ userDetail }) => { divisions={requestDetails.divisions} /> )} + {showOIPCDetails && ( + + )} { + const oipcData = [ + { oipcNumber: "F23-12345", reviewType: "Complaint", reason: "Deemed Refusal", status: "Inquiry", isInquiry: false, inquiryDate: null, investigator: "Filip Forsberg", outcome: "Withdrawn", isJudicalReview: false, isSubAppeal: false }, + { oipcNumber: "F23-12346", reviewType: "Review", reason: "Other", status: "Mediation", isInquiry: false, investigator: "Peter Forsberg", outcome: "Closed", isJudicalReview: false, isSubAppeal: true }, + { oipcNumber: "F23-12347", reviewType: "Investigation", reason: "TPN-21", status: "Awaiting Order", isInquiry: false, investigator: "Quinn Hughes", outcome: "Abandoned", isJudicalReview: true, isSubAppeal: true } + ] + + const useStyles = makeStyles({ + heading: { + color: '#FFF', + fontSize: '16px !important', + fontWeight: 'bold !important' + }, + accordionSummary: { + flexDirection: 'row-reverse' + } + }); + const classes = useStyles(); + + return ( +
+ + }> + OIPC Details + + + + + + +
+ ); +} + +export default OIPCDetails; + +//IDEA = MasterData is held in a oipcData [{}] state (there is a backend api call to generate the existing oipc data). This is mapped in OIPCDetailsList where each elm is mapped as a OIPCItem. Each OIPC Item has EDITABLE Fields (unless oipcObj outcome value exists? -> therefore we disable the field) +//EACH OIPCITEM HAS ITS OWN INTERNAL STATE WE CAN change and if changed -> the oipcData state wil change as well +// When add button is clicked, we add a new oipcObj to the oipcData state which then creates a new oipcITEM with its own default state which can be edited. +// if any oipcObjs in the oipcData state are missing any of the mandatory fields -> Save button cannot be selected./is disalbed +// When save button is enabled and clicked -> we send the backend api requeset and save the oipc data in backend by sending the master oipc data over. \ No newline at end of file diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/MandatoryFields.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/MandatoryFields.jsx new file mode 100644 index 000000000..e69de29bb diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx new file mode 100644 index 000000000..e41438981 --- /dev/null +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx @@ -0,0 +1,14 @@ +const OIPCDetailsList = (props) => { + const {oipcData} = props; + const OIPCItems = oipcData?.map((oipcObj, index) => { + return oipcObj.oipcNumber; + }) + + return ( + <> + {OIPCItems} + + ); +} + +export default OIPCDetailsList; \ No newline at end of file diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx new file mode 100644 index 000000000..e69de29bb diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcdetails.scss b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcdetails.scss new file mode 100644 index 000000000..e9129c6ca --- /dev/null +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcdetails.scss @@ -0,0 +1,34 @@ + +.align-division{ + text-align: center; +} + +.divisions-row{ + font-weight: bold; + font-size: 16px; + margin-bottom: 20px; +} + +.arrow { + display: inline-flex; + + .line { + margin-top: 14px; + // width: 320px; + width: 258px; + background: #979797; + height: 1px; + float: left; + } + + .point { + width: 0; + height: 0; + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + border-left: 10px solid #979797; + float: right; + margin-top: 9px; + } +} + \ No newline at end of file From 8a699ead916847c54fe132e0ddd07cb714e24ae6 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Wed, 15 Nov 2023 17:08:32 -0800 Subject: [PATCH 009/238] Base design and fields completed. WIP finalziing style/design + incorporating state --- .../FOI/FOIRequest/OIPCDetails/Index.jsx | 9 +- .../OIPCDetails/OIPCDetailsList.jsx | 13 +- .../FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 151 ++++++++++++++++++ 3 files changed, 164 insertions(+), 9 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx index 903355be5..7267752d7 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx @@ -1,5 +1,4 @@ import OIPCDetailsList from "./OIPCDetailsList"; -import './oipcdetails.scss'; import Accordion from '@material-ui/core/Accordion'; import AccordionSummary from '@material-ui/core/AccordionSummary'; import AccordionDetails from '@material-ui/core/AccordionDetails'; @@ -10,9 +9,9 @@ import { makeStyles } from '@material-ui/styles'; const OIPCDetails = (props) => { const oipcData = [ - { oipcNumber: "F23-12345", reviewType: "Complaint", reason: "Deemed Refusal", status: "Inquiry", isInquiry: false, inquiryDate: null, investigator: "Filip Forsberg", outcome: "Withdrawn", isJudicalReview: false, isSubAppeal: false }, - { oipcNumber: "F23-12346", reviewType: "Review", reason: "Other", status: "Mediation", isInquiry: false, investigator: "Peter Forsberg", outcome: "Closed", isJudicalReview: false, isSubAppeal: true }, - { oipcNumber: "F23-12347", reviewType: "Investigation", reason: "TPN-21", status: "Awaiting Order", isInquiry: false, investigator: "Quinn Hughes", outcome: "Abandoned", isJudicalReview: true, isSubAppeal: true } + { oipcNumber: "F23-12345", reviewType: "Complaint", reason: "Deemed Refusal", status: "Inquiry", isInquiry: false, inquiryDate: null, receivedDate: "05-08-2022", complyDate: "10-10-2023", investigator: "Filip Forsberg", outcome: "Withdrawn", isJudicalReview: false, isSubAppeal: false }, + { oipcNumber: "F23-12346", reviewType: "Review", reason: "Other", status: "Mediation", isInquiry: false, inquiryDate: null, receivedDate: "09-08-2022", complyDate: "12-10-2022", investigator: "Peter Forsberg", outcome: "Closed", isJudicalReview: false, isSubAppeal: true }, + { oipcNumber: "F23-12347", reviewType: "Investigation", reason: "TPN-21", status: "Awaiting Order", isInquiry: false, inquiryDate: null, receivedDate: "11-08-2022", complyDate: "01-10-2023", investigator: "Quinn Hughes", outcome: "Abandoned", isJudicalReview: true, isSubAppeal: true } ] const useStyles = makeStyles({ @@ -35,7 +34,7 @@ const OIPCDetails = (props) => { - +
diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx index e41438981..552c8d4fe 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx @@ -1,13 +1,18 @@ +import OIPCItem from "./OIPCItem"; + const OIPCDetailsList = (props) => { const {oipcData} = props; + const OIPCItems = oipcData?.map((oipcObj, index) => { - return oipcObj.oipcNumber; - }) + return ( + + ); + }); return ( - <> +
{OIPCItems} - +
); } diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index e69de29bb..039d879a3 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -0,0 +1,151 @@ +import { TextField, Typography, Select, FormControl, FormControlLabel, MenuItem, InputLabel, Grid, Checkbox } from '@material-ui/core'; +import { useState } from "react"; + +const OIPCItem = (props) => { + const {oipcObj} = props; + + const [oipcData, setOipcData] = useState({ + oipcNumber: "", + reviewType: "", + reason: "", + status: "", + isInquiry: false, + inquiryDate: null, + receivedDate: "", + complyDate: "", + investigator: "", + outcome: "", + isJudicalReview: true, + isSubAppeal: true + }); + + const handleReviewType = () => { + console.log("BANG") + } + + return ( + + + + + + } + variant="outlined" + fullWidth + value={oipcData.reviewType} + label="Review Type" + onChange={handleReviewType} + required={true} + > + Complaint + Review + Investigation + + + + } + variant="outlined" + fullWidth + value={oipcData.reason} + label="Reason" + onChange={handleReviewType} + required={true} + > + Adequate search + Application of Exceptions + Deemed Refusal + Extension + Fee Amount + Fee Waiver + Records do Not Exist + Duty to Assist + TPN - 22 + TPN - 21 + TPN - 18.1 + Reg 3 + Reg 4 + Reg 5 + s. 43 + Other + + + + } + variant="outlined" + fullWidth + value={oipcData.status} + label="Status" + onChange={handleReviewType} + required={true} + > + Mediation + Investigation + Inquiry + Awaiting Order + Closed + + + + + + + } + variant="outlined" + fullWidth + value={oipcData.outcome} + label="Outcome" + onChange={handleReviewType} + required={true} + > + Abandoned + Withdrawn + Resolved in Mediation + Closed + + + + In Inquiry? + } label="Yes" /> + } label="No" /> + + + In Judicial Review? + } label="Yes" /> + } label="No" /> + + + In Subsequent Appeal? + } label="Yes" /> + } label="No" /> + + + ); +} + +export default OIPCItem; \ No newline at end of file From 12b41fbbb69da5490b28edbcf8034a87bf38edc2 Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Thu, 16 Nov 2023 11:17:42 -0800 Subject: [PATCH 010/238] Insert amend into Outcomes table --- .../migrations/versions/3b399ca506fe_create_oipc_tables.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/request-management-api/migrations/versions/3b399ca506fe_create_oipc_tables.py b/request-management-api/migrations/versions/3b399ca506fe_create_oipc_tables.py index c4f22eccb..e426ec587 100644 --- a/request-management-api/migrations/versions/3b399ca506fe_create_oipc_tables.py +++ b/request-management-api/migrations/versions/3b399ca506fe_create_oipc_tables.py @@ -93,7 +93,8 @@ def upgrade(): ('Abandoned', True), ('Withdrawn', True), ('Resolved in Mediation', True), - ('Closed', True);commit;''') + ('Closed', True), + ('Amend', True);commit;''') op.execute('''INSERT INTO public."OIPCInquiryOutcomes" (name, isactive) VALUES From 7f382c4216ffd153c1ed1b17689ecee70b6e2d5d Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Thu, 16 Nov 2023 17:07:45 -0800 Subject: [PATCH 011/238] Added revised inputs per new ACS. Added additonal styling and added deleting of oipcs from FE. WIP Finalziing styling + state managemtnt of oipcs + BE call --- .../FOI/FOIRequest/OIPCDetails/Index.jsx | 45 ++- .../OIPCDetails/OIPCDetailsList.jsx | 12 +- .../FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 286 ++++++++++-------- .../FOIRequest/OIPCDetails/oipcdetails.scss | 5 + 4 files changed, 204 insertions(+), 144 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx index 7267752d7..f5474df3b 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx @@ -1,3 +1,4 @@ +import { useState } from 'react'; import OIPCDetailsList from "./OIPCDetailsList"; import Accordion from '@material-ui/core/Accordion'; import AccordionSummary from '@material-ui/core/AccordionSummary'; @@ -8,12 +9,11 @@ import Button from '@material-ui/core/Button'; import { makeStyles } from '@material-ui/styles'; const OIPCDetails = (props) => { - const oipcData = [ - { oipcNumber: "F23-12345", reviewType: "Complaint", reason: "Deemed Refusal", status: "Inquiry", isInquiry: false, inquiryDate: null, receivedDate: "05-08-2022", complyDate: "10-10-2023", investigator: "Filip Forsberg", outcome: "Withdrawn", isJudicalReview: false, isSubAppeal: false }, - { oipcNumber: "F23-12346", reviewType: "Review", reason: "Other", status: "Mediation", isInquiry: false, inquiryDate: null, receivedDate: "09-08-2022", complyDate: "12-10-2022", investigator: "Peter Forsberg", outcome: "Closed", isJudicalReview: false, isSubAppeal: true }, - { oipcNumber: "F23-12347", reviewType: "Investigation", reason: "TPN-21", status: "Awaiting Order", isInquiry: false, inquiryDate: null, receivedDate: "11-08-2022", complyDate: "01-10-2023", investigator: "Quinn Hughes", outcome: "Abandoned", isJudicalReview: true, isSubAppeal: true } - ] - + const [oipcData, setOipcData] = useState([ + { oipcNumber: "F23-12345", reviewType: "Complaint", reason: "Deemed Refusal", status: "Inquiry", isInquiry: false, inquiryDate: null, receivedDate: "05-08-2022", investigator: "Filip Forsberg", outcome: "Withdrawn", isJudicalReview: false, isSubAppeal: false }, + { oipcNumber: "F23-12346", reviewType: "Review", reason: "Other", status: "Mediation", isInquiry: false, inquiryDate: null, receivedDate: "09-08-2022", investigator: "Peter Forsberg", outcome: "Closed", isJudicalReview: false, isSubAppeal: true }, + { oipcNumber: "F23-12347", reviewType: "Investigation", reason: "TPN-21", status: "Awaiting Order", isInquiry: false, inquiryDate: null, receivedDate: "11-08-2022", investigator: "Quinn Hughes", outcome: "Abandoned", isJudicalReview: true, isSubAppeal: true } + ]); const useStyles = makeStyles({ heading: { color: '#FFF', @@ -24,8 +24,35 @@ const OIPCDetails = (props) => { flexDirection: 'row-reverse' } }); - const classes = useStyles(); + const classes = useStyles(); + //Function to Add an OIPC + const addOIPC = () => { + setOipcData((prev) => { + return [...prev, { + oipcNumber: "", + reviewType: "", + reason: "", + status: "", + isInquiry: false, + inquiryDate: null, + receivedDate: "", + complyDate: "", + investigator: "", + outcome: "", + isJudicalReview: false, + isSubAppeal: false + }]; + }) + } + //Function to Remove an OIPC + const removeOIPC = (oipcNo) => { + setOipcData((prev) => { + const previousOIPCData = [...prev]; + return previousOIPCData.filter(oipc => oipcNo !== oipc.oipcNumber); + }); + } + return (
@@ -33,8 +60,8 @@ const OIPCDetails = (props) => { OIPC Details - - + +
diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx index 552c8d4fe..00e31392c 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx @@ -1,11 +1,19 @@ import OIPCItem from "./OIPCItem"; +import Divider from '@material-ui/core/Divider'; +import './oipcdetails.scss'; +import Button from '@material-ui/core/Button'; const OIPCDetailsList = (props) => { - const {oipcData} = props; + const {oipcData, removeOIPC} = props; + console.log("TEST THIS", oipcData); const OIPCItems = oipcData?.map((oipcObj, index) => { return ( - + <> + + + {index !== (oipcData.length - 1) && } + ); }); diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index 039d879a3..33f45b539 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -1,22 +1,24 @@ -import { TextField, Typography, Select, FormControl, FormControlLabel, MenuItem, InputLabel, Grid, Checkbox } from '@material-ui/core'; +import { TextField, FormControlLabel, MenuItem, Grid, Checkbox } from '@material-ui/core'; import { useState } from "react"; const OIPCItem = (props) => { const {oipcObj} = props; - const [oipcData, setOipcData] = useState({ - oipcNumber: "", - reviewType: "", - reason: "", - status: "", - isInquiry: false, + console.log(oipcObj); + + const [oipc, setOipc] = useState({ + oipcNumber: oipcObj?.oipcNumber, + reviewType: oipcObj?.reviewType, + reason: oipcObj?.reason, + status: oipcObj?.status, + isInquiry: oipcObj?.isInquiry, inquiryDate: null, - receivedDate: "", - complyDate: "", - investigator: "", - outcome: "", - isJudicalReview: true, - isSubAppeal: true + receivedDate: oipcObj?.receivedDate, + complyDate: oipcObj?.complyDate, + investigator: oipcObj?.investigator, + outcome: oipcObj?.outcome, + isJudicalReview: oipcObj?.isJudicalReview, + isSubAppeal: oipcObj?.isSubAppeal, }); const handleReviewType = () => { @@ -24,127 +26,145 @@ const OIPCItem = (props) => { } return ( - - - - - - } - variant="outlined" - fullWidth - value={oipcData.reviewType} - label="Review Type" - onChange={handleReviewType} - required={true} - > - Complaint - Review - Investigation - - - - } - variant="outlined" - fullWidth - value={oipcData.reason} - label="Reason" - onChange={handleReviewType} - required={true} - > - Adequate search - Application of Exceptions - Deemed Refusal - Extension - Fee Amount - Fee Waiver - Records do Not Exist - Duty to Assist - TPN - 22 - TPN - 21 - TPN - 18.1 - Reg 3 - Reg 4 - Reg 5 - s. 43 - Other - - - - } - variant="outlined" - fullWidth - value={oipcData.status} - label="Status" - onChange={handleReviewType} - required={true} - > - Mediation - Investigation - Inquiry - Awaiting Order - Closed - - - - - - - } - variant="outlined" - fullWidth - value={oipcData.outcome} - label="Outcome" - onChange={handleReviewType} - required={true} - > - Abandoned - Withdrawn - Resolved in Mediation - Closed - - - - In Inquiry? - } label="Yes" /> - } label="No" /> - - - In Judicial Review? - } label="Yes" /> - } label="No" /> - - - In Subsequent Appeal? - } label="Yes" /> - } label="No" /> + <> + + + } + InputLabelProps={{ shrink: true }} + /> + + + } + InputLabelProps={{ shrink: true }} + type="date" + InputProps={{inputProps: { max: new Date()} }} + /> + + + } + variant="outlined" + fullWidth + value={oipc.reviewType} + label="Review Type" + onChange={handleReviewType} + required={true} + > + Complaint + Review + Investigation + + + + } + variant="outlined" + fullWidth + value={oipc.reason} + label="Reason" + onChange={handleReviewType} + required={true} + > + Adequate search + Application of Exceptions + Deemed Refusal + Extension + Fee Amount + Fee Waiver + Records do Not Exist + Duty to Assist + TPN - 22 + TPN - 21 + TPN - 18.1 + Reg 3 + Reg 4 + Reg 5 + s. 43 + Other + + + + } + variant="outlined" + fullWidth + value={oipc.status} + label="Status" + onChange={handleReviewType} + required={true} + > + Mediation + Investigation + Inquiry + Awaiting Order + Closed + + + + + + + } + variant="outlined" + fullWidth + value={oipc.outcome} + label="Outcome" + onChange={handleReviewType} + required={true} + > + Abandoned + Withdrawn + Resolved in Mediation + Closed + + - +
+
+

In Inquiry?

+ } label="Yes" /> + } label="No" /> +
+
+

In Judicial Review?

+ } label="Yes" /> + } label="No" /> +
+
+

In Subsequent Appeal?

+ } label="Yes" /> + } label="No" /> +
+
+ ); } diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcdetails.scss b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcdetails.scss index e9129c6ca..e226fc3e7 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcdetails.scss +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcdetails.scss @@ -31,4 +31,9 @@ margin-top: 9px; } } + +.MuiDivider-root { + margin: 10px 0px 30px 0px !important; + height: 1.5px !important; +} \ No newline at end of file From 278447931c597d6e230277ea0f3d205f9f95f45f Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Fri, 17 Nov 2023 13:32:21 -0800 Subject: [PATCH 012/238] Styling 1.0 completed. WIP State management + API Call + Final Styling --- .../components/FOI/FOIRequest/OIPCDetails/Index.jsx | 10 ++++++++-- .../FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx | 11 ++++++++--- .../FOI/FOIRequest/OIPCDetails/oipcdetails.scss | 2 +- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx index f5474df3b..74f373ad8 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx @@ -5,8 +5,9 @@ import AccordionSummary from '@material-ui/core/AccordionSummary'; import AccordionDetails from '@material-ui/core/AccordionDetails'; import Typography from '@material-ui/core/Typography'; import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; -import Button from '@material-ui/core/Button'; import { makeStyles } from '@material-ui/styles'; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faCirclePlus } from '@fortawesome/free-solid-svg-icons'; const OIPCDetails = (props) => { const [oipcData, setOipcData] = useState([ @@ -61,7 +62,12 @@ const OIPCDetails = (props) => { - +
+ +

Add Additional OIPC Complaint

+
diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx index 00e31392c..b12aa4236 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx @@ -1,7 +1,8 @@ import OIPCItem from "./OIPCItem"; import Divider from '@material-ui/core/Divider'; import './oipcdetails.scss'; -import Button from '@material-ui/core/Button'; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faTrash } from '@fortawesome/free-solid-svg-icons'; const OIPCDetailsList = (props) => { const {oipcData, removeOIPC} = props; @@ -10,8 +11,12 @@ const OIPCDetailsList = (props) => { const OIPCItems = oipcData?.map((oipcObj, index) => { return ( <> - - +
+ +
+ {index !== (oipcData.length - 1) && } ); diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcdetails.scss b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcdetails.scss index e226fc3e7..4683c050f 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcdetails.scss +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcdetails.scss @@ -33,7 +33,7 @@ } .MuiDivider-root { - margin: 10px 0px 30px 0px !important; + margin: 10px 0px 16px 0px !important; height: 1.5px !important; } \ No newline at end of file From 89bab58fbed5767b007dfb467a6a55786d87560f Mon Sep 17 00:00:00 2001 From: "sumathi.thirumani" Date: Fri, 17 Nov 2023 15:35:57 -0800 Subject: [PATCH 013/238] Draft commit. --- .../versions/455a24da8c58_oipc_txn_changes.py | 50 +++++++++++++++++++ .../request_api/models/FOIMinistryRequests.py | 8 ++- .../request_api/models/FOIRequestOIPC.py | 47 +++++++++++++++++ .../request_api/schemas/foirequestwrapper.py | 30 +++++++++++ .../services/external/keycloakadminservice.py | 10 ++-- .../foirequest/requestservicebuilder.py | 31 ++++++++++++ .../foirequest/requestservicegetter.py | 26 ++++++++++ 7 files changed, 196 insertions(+), 6 deletions(-) create mode 100644 request-management-api/migrations/versions/455a24da8c58_oipc_txn_changes.py create mode 100644 request-management-api/request_api/models/FOIRequestOIPC.py diff --git a/request-management-api/migrations/versions/455a24da8c58_oipc_txn_changes.py b/request-management-api/migrations/versions/455a24da8c58_oipc_txn_changes.py new file mode 100644 index 000000000..764909fc4 --- /dev/null +++ b/request-management-api/migrations/versions/455a24da8c58_oipc_txn_changes.py @@ -0,0 +1,50 @@ +"""empty message + +Revision ID: 455a24da8c58 +Revises: 3b399ca506fe +Create Date: 2023-11-15 12:31:33.274617 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = '455a24da8c58' +down_revision = '3b399ca506fe' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('FOIMinistryRequests', sa.Column('isoipcreview', sa.Boolean, nullable=True,default=False)) + op.create_table('FOIRequestOIPC', + sa.Column('oipcid', sa.Integer(), autoincrement=True, nullable=False), + sa.Column('foiministryrequest_id', sa.Integer(), nullable=False), + sa.Column('foiministryrequestversion_id', sa.Integer(), nullable=False), + sa.Column('oipcno', sa.String(length=250), nullable=False), + sa.Column('investigator', sa.String(length=500), nullable=True), + sa.Column('reviewtypeid', sa.Integer(), nullable=False), + sa.Column('reasonid', sa.Integer(), nullable=False), + sa.Column('statusid', sa.Integer(), nullable=True), + sa.Column('outcomeid', sa.Integer(), nullable=True), + sa.Column('isinquiry', sa.Boolean(), nullable=True), + sa.Column('isjudicialreview', sa.Boolean(), nullable=True), + sa.Column('issubsequentappeal', sa.Boolean(), nullable=True), + sa.Column('inquiryattributes', sa.JSON, nullable=True), + sa.Column('created_at', sa.DateTime(), nullable=False), + sa.Column('createdby', sa.String(length=120), nullable=False), + sa.Column('updated_at', sa.DateTime(), nullable=True), + sa.Column('updatedby', sa.String(length=120), nullable=True), + sa.ForeignKeyConstraint(['foiministryrequest_id', 'foiministryrequestversion_id'], ['FOIMinistryRequests.foiministryrequestid', 'FOIMinistryRequests.version'], ), + sa.PrimaryKeyConstraint('oipcid') + ) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('FOIMinistryRequests', 'isoipcreview') + op.drop_table('FOIRequestOIPC') + # ### end Alembic commands ### diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index cd6e2a8e9..dfb5cfbf5 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -92,6 +92,10 @@ class FOIMinistryRequest(db.Model): "FOIMinistryRequest.version==FOIMinistryRequestDocument.foiministryrequestversion_id)") extensions = relationship('FOIRequestExtension', primaryjoin="and_(FOIMinistryRequest.foiministryrequestid==FOIRequestExtension.foiministryrequest_id, " "FOIMinistryRequest.version==FOIRequestExtension.foiministryrequestversion_id)") + + oipcreviews = relationship('FOIRequestOIPC', primaryjoin="and_(FOIMinistryRequest.foiministryrequestid==FOIRequestOIPC.foiministryrequest_id, " + "FOIMinistryRequest.version==FOIRequestOIPC.foiministryrequestversion_id)") + assignee = relationship('FOIAssignee', foreign_keys="[FOIMinistryRequest.assignedto]") ministryassignee = relationship('FOIAssignee', foreign_keys="[FOIMinistryRequest.assignedministryperson]") @@ -99,6 +103,8 @@ class FOIMinistryRequest(db.Model): "FOIMinistryRequest.version==FOIMinistryRequestSubjectCode.foiministryrequestversion)") isofflinepayment = db.Column(db.Boolean, unique=False, nullable=True,default=False) + isoipcreview = db.Column(db.Boolean, unique=False, nullable=True,default=False) + @classmethod def getrequest(cls,ministryrequestid): request_schema = FOIMinistryRequestSchema(many=False) @@ -1307,5 +1313,5 @@ class Meta: 'foirequest.receivedmodeid','requeststatus.requeststatusid','requeststatus.name','programarea.bcgovcode', 'programarea.name','foirequest_id','foirequestversion_id','created_at','updated_at','createdby','assignedministryperson', 'assignedministrygroup','cfrduedate','closedate','closereasonid','closereason.name', - 'assignee.firstname','assignee.lastname','ministryassignee.firstname','ministryassignee.lastname', 'axisrequestid', 'axissyncdate', 'requestpagecount', 'linkedrequests', 'ministrysignoffapproval', 'identityverified','originalldd') + 'assignee.firstname','assignee.lastname','ministryassignee.firstname','ministryassignee.lastname', 'axisrequestid', 'axissyncdate', 'requestpagecount', 'linkedrequests', 'ministrysignoffapproval', 'identityverified','originalldd','isoipcreview') diff --git a/request-management-api/request_api/models/FOIRequestOIPC.py b/request-management-api/request_api/models/FOIRequestOIPC.py new file mode 100644 index 000000000..1aacce9fd --- /dev/null +++ b/request-management-api/request_api/models/FOIRequestOIPC.py @@ -0,0 +1,47 @@ +from flask.app import Flask +from sqlalchemy.sql.schema import ForeignKey +from .db import db, ma +from datetime import datetime +from sqlalchemy.orm import relationship,backref +from .default_method_result import DefaultMethodResult +from sqlalchemy.dialects.postgresql import JSON, UUID +from sqlalchemy.sql.expression import distinct +from sqlalchemy import text, and_, func +import logging +import json +from sqlalchemy.dialects.postgresql import JSON, insert + +class FOIRequestOIPC(db.Model): + # Name of the table in our database + __tablename__ = 'FOIRequestOIPC' + # Defining the columns + oipcid = db.Column(db.Integer, primary_key=True,autoincrement=True) + foiministryrequest_id =db.Column(db.Integer, db.ForeignKey('FOIMinistryRequests.foiministryrequestid')) + foiministryrequestversion_id =db.Column(db.Integer, db.ForeignKey('FOIMinistryRequests.version')) + oipcno = db.Column(db.String(120), unique=False, nullable=True) + reviewtypeid = db.Column(db.Integer, unique=False, nullable=False) + reasonid = db.Column(db.Integer, unique=False, nullable=False) + statusid = db.Column(db.Integer, unique=False, nullable=True) + outcomeid = db.Column(db.Integer, unique=False, nullable=True) + isinquiry = db.Column(db.Boolean, unique=False, nullable=True) + inquiryattributes = db.Column(JSON, unique=False, nullable=True) + isjudicialreview = db.Column(db.Boolean, unique=False, nullable=True) + issubsequentappeal = db.Column(db.Boolean, unique=False, nullable=True) + investigator = db.Column(db.String(500), unique=False, nullable=True) + created_at = db.Column(db.DateTime, default=datetime.now) + createdby = db.Column(db.String(120), unique=False, nullable=False) + updated_at = db.Column(db.DateTime, nullable=True) + updatedby = db.Column(db.String(120), unique=False, nullable=True) + + + @classmethod + def getoipc(cls,ministryrequestid,ministryrequestversion): + oipc_schema = FOIRequestOIPCSchema(many=True) + _oipclist = db.session.query(FOIRequestOIPC).filter(FOIRequestOIPC.foiministryrequest_id == ministryrequestid , FOIRequestOIPC.foiministryrequestversion_id == ministryrequestversion).order_by(FOIRequestOIPC.oipcid.asc()).all() + divisioninfos = oipc_schema.dump(_oipclist) + return divisioninfos + + +class FOIRequestOIPCSchema(ma.Schema): + class Meta: + fields = ('oipcid', 'version', 'ministryrequestid', 'investigator','ministryversion','oipcno','reviewtypeid','reasonid','statusid','outcomeid','isinquiry','inquiryattributes','isjudicialreview','issubsequentappeal','isactive','created_at','createdby','updated_at','updatedby') \ No newline at end of file diff --git a/request-management-api/request_api/schemas/foirequestwrapper.py b/request-management-api/request_api/schemas/foirequestwrapper.py index efdb027ac..38a9ab1dc 100644 --- a/request-management-api/request_api/schemas/foirequestwrapper.py +++ b/request-management-api/request_api/schemas/foirequestwrapper.py @@ -53,6 +53,33 @@ class Meta: # pylint: disable=too-few-public-methods documentpath = fields.Str(data_key="documentpath",allow_none=False, validate=[validate.Length(max=1000, error=MAX_EXCEPTION_MESSAGE)]) filename = fields.Str(data_key="filename",allow_none=False, validate=[validate.Length(max=120, error=MAX_EXCEPTION_MESSAGE)]) category = fields.Str(data_key="category",allow_none=False, validate=[validate.Length(max=120, error=MAX_EXCEPTION_MESSAGE)]) + +class FOIOIPCInquirySchema(Schema): + class Meta: # pylint: disable=too-few-public-methods + """Exclude unknown fields in the deserialized output.""" + + unknown = EXCLUDE + inquirydate = fields.Str(data_key="inquirydate",allow_none=True) + orderno = fields.Str(data_key="orderno",allow_none=True) + inquiryoutcome = fields.Str(data_key="outcome",allow_none=True) + +class FOIMinistryRequestOIPCSchema(Schema): + class Meta: # pylint: disable=too-few-public-methods + """Exclude unknown fields in the deserialized output.""" + + unknown = EXCLUDE + oipcno = fields.Str(data_key="oipcno") + reviewtypeid = fields.Int(data_key="reviewtypeid") + reasonid = fields.Int(data_key="reasonid") + statusid = fields.Int(data_key="statusid") + outcomeid = fields.Int(data_key="outcomeid") + investigator = fields.Str(data_key="investigator",allow_none=True, validate=[validate.Length(max=500, error=MAX_EXCEPTION_MESSAGE)]) + isinquiry = fields.Bool(data_key="isinquiry") + isjudicialreview = fields.Bool(data_key="isjudicialreview") + issubsequentappeal = fields.Bool(data_key="issubsequentappeal") + inquiryattributes = fields.Nested(FOIOIPCInquirySchema, data_key="inquiryattributes", allow_none=True) + + class FOIRequestWrapperSchema(Schema): class Meta: # pylint: disable=too-few-public-methods @@ -110,6 +137,7 @@ class Meta: # pylint: disable=too-few-public-methods correctionalServiceNumber = fields.Str(data_key="correctionalServiceNumber",allow_none=True, validate=[validate.Length(max=50, error=MAX_EXCEPTION_MESSAGE)]) publicServiceEmployeeNumber = fields.Str(data_key="publicServiceEmployeeNumber",allow_none=True, validate=[validate.Length(max=50, error=MAX_EXCEPTION_MESSAGE)]) isiaorestricted = fields.Bool(data_key="isiaorestricted") + isoipcreview = fields.Bool(data_key="isoipcreview") selectedMinistries = fields.Nested(FOIMinistryRequestWrapperSchema, many=True) additionalPersonalInfo = fields.Nested(FOIAdditionallPersonalInfoWrapperSchema,required=False,allow_none=True) @@ -120,6 +148,8 @@ class Meta: # pylint: disable=too-few-public-methods linkedRequests = fields.List(fields.Dict(data_key="linkedRequests", required=False)) identityVerified = fields.Str(data_key="identityVerified",allow_none=True) + oipcdetails = fields.Nested(FOIMinistryRequestOIPCSchema, many=True,allow_none=True) + class EditableFOIMinistryRequestWrapperSchema(Schema): class Meta: # pylint: disable=too-few-public-methods diff --git a/request-management-api/request_api/services/external/keycloakadminservice.py b/request-management-api/request_api/services/external/keycloakadminservice.py index 5ec6af21e..3a632d34b 100644 --- a/request-management-api/request_api/services/external/keycloakadminservice.py +++ b/request-management-api/request_api/services/external/keycloakadminservice.py @@ -24,8 +24,8 @@ class KeycloakAdminService: def get_token(self): _accesstoken=None try: - cache_client = redis.from_url(self.cache_redis_url,decode_responses=True) - _accesstoken = cache_client.get("foi:kcsrcacnttoken") + #cache_client = redis.from_url(self.cache_redis_url,decode_responses=True) + _accesstoken = None #cache_client.get("foi:kcsrcacnttoken") if _accesstoken is None: url = '{0}/auth/realms/{1}/protocol/openid-connect/token'.format(self.keycloakhost,self.keycloakrealm) params = { @@ -38,11 +38,11 @@ def get_token(self): } x = requests.post(url, params, verify=True).content.decode('utf-8') _accesstoken = str(ast.literal_eval(x)['access_token']) - cache_client.set("foi:kcsrcacnttoken",_accesstoken,ex=int(self.kctokenexpiry)) + #cache_client.set("foi:kcsrcacnttoken",_accesstoken,ex=int(self.kctokenexpiry)) except BusinessException as exception: print("Error happened while accessing token on KeycloakAdminService {0}".format(exception.message)) - finally: - cache_client = None + # finally: + # cache_client = None return _accesstoken diff --git a/request-management-api/request_api/services/foirequest/requestservicebuilder.py b/request-management-api/request_api/services/foirequest/requestservicebuilder.py index 4f6db7aa5..790cbc540 100644 --- a/request-management-api/request_api/services/foirequest/requestservicebuilder.py +++ b/request-management-api/request_api/services/foirequest/requestservicebuilder.py @@ -8,6 +8,8 @@ from request_api.models.FOIRequestApplicants import FOIRequestApplicant from request_api.models.FOIRequestApplicantMappings import FOIRequestApplicantMapping from request_api.models.FOIRequestTeams import FOIRequestTeam +from request_api.models.FOIRequestOIPC import FOIRequestOIPC + from datetime import datetime as datetime2 from request_api.utils.enums import MinistryTeamWithKeycloackGroup from request_api.services.foirequest.requestserviceconfigurator import requestserviceconfigurator @@ -34,6 +36,10 @@ def createministry(self, requestschema, ministry, activeversion, userid, filenum foiministryrequest.linkedrequests = requestschema.get("linkedRequests") foiministryrequest.identityverified = requestschema.get("identityVerified") foiministryrequest.originalldd = requestschema.get("originalDueDate") + if requestschema.get("isoipcreview") is not None and requestschema.get("isoipcreview") != "": + foiministryrequest.isoipcreview = requestschema.get("isoipcreview") + foiministryrequest.oipcreviews = self.prepareoipc(requestschema, ministryid, activeversion, userid) + if requestschema.get("cfrDueDate") is not None and requestschema.get("cfrDueDate") != "": foiministryrequest.cfrduedate = requestschema.get("cfrDueDate") startdate = "" @@ -126,6 +132,31 @@ def createpersonalattribute(self, name, value,attributetypes, userid): personalattribute.attributevalue = value return personalattribute + def prepareoipc(self, requestschema, ministryrequestid, version, userid): + oipcarr = [] + if 'oipcdetails' in requestschema: + for oipc in requestschema['oipcdetails']: + oipcreview = FOIRequestOIPC() + oipcreview.foiministryrequest_id = ministryrequestid + oipcreview.foiministryrequestversion_id=version + oipcreview.oipcno = oipc["oipcno"] + oipcreview.reviewtypeid = oipc["reviewtypeid"] + oipcreview.reasonid = oipc["reasonid"] + oipcreview.statusid = oipc["statusid"] + oipcreview.outcomeid = oipc["outcomeid"] + oipcreview.investigator = oipc["investigator"] + oipcreview.isinquiry = oipc["isinquiry"] + oipcreview.isjudicialreview = oipc["isjudicialreview"] + oipcreview.issubsequentappeal = oipc["issubsequentappeal"] + oipcreview.issubsequentappeal = oipc["issubsequentappeal"] + oipcreview.isactive = True + if oipc["isinquiry"] == True: + oipcreview.inquiryattributes = oipc["inquiryattributes"] + oipcreview.createdby=userid + oipcreview.created_at= datetime2.now().isoformat() + oipcarr.append(oipcreview) + return oipcarr + def isNotBlankorNone(self, dataschema, key, location): if location == "main": diff --git a/request-management-api/request_api/services/foirequest/requestservicegetter.py b/request-management-api/request_api/services/foirequest/requestservicegetter.py index e5ae2c249..d3fedf68b 100644 --- a/request-management-api/request_api/services/foirequest/requestservicegetter.py +++ b/request-management-api/request_api/services/foirequest/requestservicegetter.py @@ -8,6 +8,7 @@ from request_api.models.FOIRequestApplicantMappings import FOIRequestApplicantMapping from request_api.models.FOIMinistryRequestSubjectCodes import FOIMinistryRequestSubjectCode from request_api.models.FOIRestrictedMinistryRequests import FOIRestrictedMinistryRequest +from request_api.models.FOIRequestOIPC import FOIRequestOIPC from dateutil.parser import parse from request_api.services.cfrfeeservice import cfrfeeservice from request_api.services.paymentservice import paymentservice @@ -165,6 +166,8 @@ def __preparebaseinfo(self,request,foiministryrequestid,requestministry,requestm 'assignedministryperson':requestministry["assignedministryperson"], 'selectedMinistries':[{'code':requestministry['programarea.bcgovcode'],'id':requestministry['foiministryrequestid'],'name':requestministry['programarea.name'],'selected':'true'}], 'divisions': self.getdivisions(requestministrydivisions), + 'isoipcreview': requestministry['isoipcreview'], + 'oipcdetails': self.getoipcdetails(foiministryrequestid, requestministry['version']), 'onholdTransitionDate': self.getonholdtransition(foiministryrequestid), 'stateTransition': FOIMinistryRequest.getstatesummary(foiministryrequestid), 'assignedToFirstName': requestministry["assignee.firstname"] if requestministry["assignedto"] != None else None, @@ -208,6 +211,29 @@ def getdivisions(self, ministrydivisions): divisions.append(division) return divisions + def getoipcdetails(self, ministryrequestid, ministryrequestversion): + oipcdetails = [] + _oipclist = FOIRequestOIPC.getoipc(ministryrequestid, ministryrequestversion) + if _oipclist is not None: + for entry in _oipclist: + oipc = { + "oipcid": entry["oipcid"], + "reviewtypeid": entry["reviewtypeid"], + "reasonid": entry["reasonid"], + "statusid": entry["statusid"], + "outcomeid": entry["outcomeid"], + "investigator": entry["investigator"], + "isinquiry": entry["isinquiry"], + "isjudicialreview": entry["isjudicialreview"], + "issubsequentappeal": entry["issubsequentappeal"], + "inquiryattributes": entry["inquiryattributes"], + "createdby": entry["createdby"], + "created_at": parse(entry["created_at"]).strftime(self.__genericdateformat()) + } + oipcdetails.append(oipc) + return oipcdetails + + def getonholdtransition(self, foiministryrequestid): onholddate = None From 2758073ea955dc9a6ec5b1277554634b4af279cd Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Fri, 17 Nov 2023 15:57:51 -0800 Subject: [PATCH 014/238] OIPCData form/state management WIP --- .../FOIRequest/OIPCDetails/AddOIPCButton.jsx | 0 .../FOI/FOIRequest/OIPCDetails/Index.jsx | 18 ++++++-- .../OIPCDetails/OIPCDetailsList.jsx | 4 +- .../FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 42 +++++++++++++++---- 4 files changed, 52 insertions(+), 12 deletions(-) delete mode 100644 forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/AddOIPCButton.jsx diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/AddOIPCButton.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/AddOIPCButton.jsx deleted file mode 100644 index e69de29bb..000000000 diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx index 74f373ad8..f1daadc5d 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx @@ -13,7 +13,6 @@ const OIPCDetails = (props) => { const [oipcData, setOipcData] = useState([ { oipcNumber: "F23-12345", reviewType: "Complaint", reason: "Deemed Refusal", status: "Inquiry", isInquiry: false, inquiryDate: null, receivedDate: "05-08-2022", investigator: "Filip Forsberg", outcome: "Withdrawn", isJudicalReview: false, isSubAppeal: false }, { oipcNumber: "F23-12346", reviewType: "Review", reason: "Other", status: "Mediation", isInquiry: false, inquiryDate: null, receivedDate: "09-08-2022", investigator: "Peter Forsberg", outcome: "Closed", isJudicalReview: false, isSubAppeal: true }, - { oipcNumber: "F23-12347", reviewType: "Investigation", reason: "TPN-21", status: "Awaiting Order", isInquiry: false, inquiryDate: null, receivedDate: "11-08-2022", investigator: "Quinn Hughes", outcome: "Abandoned", isJudicalReview: true, isSubAppeal: true } ]); const useStyles = makeStyles({ heading: { @@ -47,12 +46,25 @@ const OIPCDetails = (props) => { }) } //Function to Remove an OIPC - const removeOIPC = (oipcNo) => { + const removeOIPC = (oipcNo, index) => { setOipcData((prev) => { const previousOIPCData = [...prev]; return previousOIPCData.filter(oipc => oipcNo !== oipc.oipcNumber); }); } + //Function to Update an OIPC + const updateOIPC = (newOIPCObj, index) => { + setOipcData((prev) => { + const previousOIPCData = [...prev]; + return previousOIPCData.map((oipc) => { + if (oipc.oipcNumber === newOIPCObj.oipcNumber) { + return newOIPCObj; + } else { + return oipc; + } + }); + }); + } return (
@@ -61,7 +73,7 @@ const OIPCDetails = (props) => { OIPC Details - +
- + {index !== (oipcData.length - 1) && } ); diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index 33f45b539..f8fc20cd6 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -2,9 +2,7 @@ import { TextField, FormControlLabel, MenuItem, Grid, Checkbox } from '@material import { useState } from "react"; const OIPCItem = (props) => { - const {oipcObj} = props; - - console.log(oipcObj); + const {oipcObj, updateOIPC} = props; const [oipc, setOipc] = useState({ oipcNumber: oipcObj?.oipcNumber, @@ -20,9 +18,40 @@ const OIPCItem = (props) => { isJudicalReview: oipcObj?.isJudicalReview, isSubAppeal: oipcObj?.isSubAppeal, }); + + console.log(oipcObj); - const handleReviewType = () => { - console.log("BANG") + const handleReviewType = (value) => { + const newOIPCObj = oipc; + newOIPCObj.reviewType = value; + updateOIPC(newOIPCObj); + } + const handleOIPCNumber = (event) => { + console.log("BANG"); + } + const handleReceivedDate = (event) => { + console.log("BANG"); + } + const handleReason = (event) => { + console.log("BANG"); + } + const handleStatus = (event) => { + console.log("BANG"); + } + const handleInvestiagtor = (event) => { + console.log("BANG"); + } + const handleOutcome = (event) => { + console.log("BANG"); + } + const handleInquiry = (event) => { + console.log("BANG"); + } + const handleJudicalReview = (event) => { + console.log("BANG"); + } + const handleSubsequentAppeal = (event) => { + console.log("BANG"); } return ( @@ -61,7 +90,7 @@ const OIPCItem = (props) => { fullWidth value={oipc.reviewType} label="Review Type" - onChange={handleReviewType} + onChange={(event) => handleReviewType(event.target.value)} required={true} > Complaint @@ -137,7 +166,6 @@ const OIPCItem = (props) => { fullWidth value={oipc.outcome} label="Outcome" - onChange={handleReviewType} required={true} > Abandoned From aa653200abdcdaf12c87eb120e184cc528e43023 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Mon, 20 Nov 2023 14:57:34 -0800 Subject: [PATCH 015/238] WIP Integration of BE + Inquiry Story + Saving of OIPC to BE + validation --- .../FOI/FOIRequest/OIPCDetails/Index.jsx | 34 +++-- .../OIPCDetails/OIPCDetailsList.jsx | 2 +- .../FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 136 +++++++++++------- 3 files changed, 103 insertions(+), 69 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx index f1daadc5d..d84b76fcc 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx @@ -10,10 +10,19 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faCirclePlus } from '@fortawesome/free-solid-svg-icons'; const OIPCDetails = (props) => { - const [oipcData, setOipcData] = useState([ - { oipcNumber: "F23-12345", reviewType: "Complaint", reason: "Deemed Refusal", status: "Inquiry", isInquiry: false, inquiryDate: null, receivedDate: "05-08-2022", investigator: "Filip Forsberg", outcome: "Withdrawn", isJudicalReview: false, isSubAppeal: false }, - { oipcNumber: "F23-12346", reviewType: "Review", reason: "Other", status: "Mediation", isInquiry: false, inquiryDate: null, receivedDate: "09-08-2022", investigator: "Peter Forsberg", outcome: "Closed", isJudicalReview: false, isSubAppeal: true }, - ]); + const createOIPCId = (oipcData) => { + if (oipcData.length > 0) { + return oipcData.map((item, index) => { + item.id = index; + return item; + }); + } + } + const [oipcData, setOipcData] = useState(createOIPCId([ + { oipcNumber: "F23-12345", reviewType: "Complaint", reason: "Extension", status: "Inquiry", isInquiry: false, inquiryDate: null, receivedDate: "2022-05-08", investigator: "Filip Forsberg", outcome: "Withdrawn", isJudicalReview: false, isSubAppeal: false }, + { oipcNumber: "F23-12346", reviewType: "Review", reason: "Other", status: "Mediation", isInquiry: false, inquiryDate: null, receivedDate: "2022-09-08", investigator: "Peter Forsberg", outcome: "Closed", isJudicalReview: false, isSubAppeal: true }, + ])); + const useStyles = makeStyles({ heading: { color: '#FFF', @@ -26,18 +35,17 @@ const OIPCDetails = (props) => { }); const classes = useStyles(); - //Function to Add an OIPC + //Functions const addOIPC = () => { setOipcData((prev) => { return [...prev, { + id: oipcData.length > 0 ? oipcData[oipcData.length - 1].id + 1 : 0, oipcNumber: "", reviewType: "", reason: "", status: "", isInquiry: false, - inquiryDate: null, receivedDate: "", - complyDate: "", investigator: "", outcome: "", isJudicalReview: false, @@ -45,19 +53,17 @@ const OIPCDetails = (props) => { }]; }) } - //Function to Remove an OIPC - const removeOIPC = (oipcNo, index) => { + const removeOIPC = (oipcId) => { setOipcData((prev) => { const previousOIPCData = [...prev]; - return previousOIPCData.filter(oipc => oipcNo !== oipc.oipcNumber); + return previousOIPCData.filter(oipc => oipcId !== oipc.id); }); } - //Function to Update an OIPC - const updateOIPC = (newOIPCObj, index) => { + const updateOIPC = (newOIPCObj) => { setOipcData((prev) => { const previousOIPCData = [...prev]; return previousOIPCData.map((oipc) => { - if (oipc.oipcNumber === newOIPCObj.oipcNumber) { + if (oipc.oipcId === newOIPCObj.oipcId) { return newOIPCObj; } else { return oipc; @@ -70,7 +76,7 @@ const OIPCDetails = (props) => {
}> - OIPC Details + OIPC DETAILS diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx index 7183448a2..e3c8ac499 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx @@ -12,7 +12,7 @@ const OIPCDetailsList = (props) => { return ( <>
-
diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index f8fc20cd6..7d42ae1c3 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -1,5 +1,7 @@ import { TextField, FormControlLabel, MenuItem, Grid, Checkbox } from '@material-ui/core'; import { useState } from "react"; +import { formatDate } from "../../../../helper/FOI/helper"; + const OIPCItem = (props) => { const {oipcObj, updateOIPC} = props; @@ -10,9 +12,7 @@ const OIPCItem = (props) => { reason: oipcObj?.reason, status: oipcObj?.status, isInquiry: oipcObj?.isInquiry, - inquiryDate: null, receivedDate: oipcObj?.receivedDate, - complyDate: oipcObj?.complyDate, investigator: oipcObj?.investigator, outcome: oipcObj?.outcome, isJudicalReview: oipcObj?.isJudicalReview, @@ -22,38 +22,51 @@ const OIPCItem = (props) => { console.log(oipcObj); const handleReviewType = (value) => { - const newOIPCObj = oipc; - newOIPCObj.reviewType = value; - updateOIPC(newOIPCObj); + updateOIPC({...oipc, reviewType: value, reason: ""}); + } + const handleOIPCNumber = (value) => { + updateOIPC({...oipc, oipcNumber: value}); } - const handleOIPCNumber = (event) => { - console.log("BANG"); + const handleReceivedDate = (value) => { + updateOIPC({...oipc, receivedDate: value}); } - const handleReceivedDate = (event) => { - console.log("BANG"); + const handleReason = (value) => { + updateOIPC({...oipc, reason: value}); } - const handleReason = (event) => { - console.log("BANG"); + const handleStatus = (value) => { + updateOIPC({...oipc, status: value}); } - const handleStatus = (event) => { - console.log("BANG"); + const handleInvestiagtor = (value) => { + updateOIPC({...oipc, investigator: value}); } - const handleInvestiagtor = (event) => { - console.log("BANG"); + const handleOutcome = (value) => { + updateOIPC({...oipc, outcome: value}); } - const handleOutcome = (event) => { - console.log("BANG"); + const handleInquiry = (value) => { + updateOIPC({...oipc, isInquiry: value}); } - const handleInquiry = (event) => { - console.log("BANG"); + const handleJudicalReview = (value) => { + updateOIPC({...oipc, isJudicalReview: value}); } - const handleJudicalReview = (event) => { - console.log("BANG"); + const handleSubsequentAppeal = (value) => { + updateOIPC({...oipc, isSubAppeal: value}); } - const handleSubsequentAppeal = (event) => { - console.log("BANG"); + //REFACTOR THIS!!! + const filterReasonOptions = (reviewType) => { + if (reviewType === "Complaint") { + return ["Adequate search","Extension", "Fee Amount", "Fee Waiver", "Duty to Assist", "Other"]; + } + if (reviewType === "Review") { + return ["Application of Exceptions", "Deemed Refusal", "TPN - 22", "TPN - 21", "TPN - 18.1", "Reg 3", "Reg 4", "Reg 5", "s. 43", "Other"]; + } + if (reviewType === "Investigation") { + return ["Other"] + } + return ["Adequate search","Extension", "Fee Amount", "Fee Waiver", "Duty to Assist", "Application of Exceptions", "Deemed Refusal", "TPN - 22", "TPN - 21", "TPN - 18.1", "Reg 3", "Reg 4", "Reg 5", "s. 43", "Other"]; } + const reasons = filterReasonOptions(oipc.reviewType) + return ( <> @@ -64,7 +77,7 @@ const OIPCItem = (props) => { variant="outlined" required={true} value={oipc.oipcNumber} - // input={} + onChange = {(event) => handleOIPCNumber(event.target.value)} InputLabelProps={{ shrink: true }} /> @@ -75,17 +88,16 @@ const OIPCItem = (props) => { variant="outlined" required={true} value={oipc.receivedDate} - // input={} + onChange = {(event) => handleReceivedDate(event.target.value)} InputLabelProps={{ shrink: true }} + InputProps={{inputProps: { max: oipc.receivedDate || formatDate(new Date())} }} type="date" - InputProps={{inputProps: { max: new Date()} }} /> } variant="outlined" fullWidth value={oipc.reviewType} @@ -102,42 +114,27 @@ const OIPCItem = (props) => { } variant="outlined" fullWidth value={oipc.reason} label="Reason" - onChange={handleReviewType} + onChange = {(event) => handleReason(event.target.value)} required={true} > - Adequate search - Application of Exceptions - Deemed Refusal - Extension - Fee Amount - Fee Waiver - Records do Not Exist - Duty to Assist - TPN - 22 - TPN - 21 - TPN - 18.1 - Reg 3 - Reg 4 - Reg 5 - s. 43 - Other + {reasons.map((reason) => { + return {reason} + })} } variant="outlined" fullWidth value={oipc.status} label="Status" - onChange={handleReviewType} + onChange = {(event) => handleStatus(event.target.value)} required={true} > Mediation @@ -153,6 +150,7 @@ const OIPCItem = (props) => { label="Investigator/Adjudicator" variant="outlined" required={true} + onChange = {(event) => handleInvestiagtor(event.target.value)} value={oipc.investigator} InputLabelProps={{ shrink: true }} /> @@ -161,8 +159,8 @@ const OIPCItem = (props) => { } variant="outlined" + onChange = {(event) => handleOutcome(event.target.value)} fullWidth value={oipc.outcome} label="Outcome" @@ -178,18 +176,48 @@ const OIPCItem = (props) => {

In Inquiry?

- } label="Yes" /> - } label="No" /> + handleInquiry(true)} + />} + label="Yes" + /> + handleInquiry(false)} + />} + label="No" + />

In Judicial Review?

- } label="Yes" /> - } label="No" /> + handleJudicalReview(true)} + />} + label="Yes" + /> + handleJudicalReview(false)} + />} + label="No" + />

In Subsequent Appeal?

- } label="Yes" /> - } label="No" /> + handleSubsequentAppeal(true)} + />} + label="Yes" + /> + handleSubsequentAppeal(false)} + />} + label="No" + />
From 04ae6a42031bd6e8e62ced3e251e9326ce5bd3bd Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Mon, 20 Nov 2023 15:27:44 -0800 Subject: [PATCH 016/238] Small code changes / fixes --- forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js | 4 +++- .../src/components/FOI/FOIRequest/OIPCDetails/Index.jsx | 4 +++- .../src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 4 ++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index 26a40787d..10c384bc8 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -1210,7 +1210,9 @@ const FOIRequest = React.memo(({ userDetail }) => { /> )} {showOIPCDetails && ( - + )} { + //Local State const createOIPCId = (oipcData) => { if (oipcData.length > 0) { return oipcData.map((item, index) => { @@ -23,6 +24,7 @@ const OIPCDetails = (props) => { { oipcNumber: "F23-12346", reviewType: "Review", reason: "Other", status: "Mediation", isInquiry: false, inquiryDate: null, receivedDate: "2022-09-08", investigator: "Peter Forsberg", outcome: "Closed", isJudicalReview: false, isSubAppeal: true }, ])); + //Styling const useStyles = makeStyles({ heading: { color: '#FFF', @@ -63,7 +65,7 @@ const OIPCDetails = (props) => { setOipcData((prev) => { const previousOIPCData = [...prev]; return previousOIPCData.map((oipc) => { - if (oipc.oipcId === newOIPCObj.oipcId) { + if (oipc.id === newOIPCObj.id) { return newOIPCObj; } else { return oipc; diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index 7d42ae1c3..dc1e6ba8e 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -60,12 +60,12 @@ const OIPCItem = (props) => { return ["Application of Exceptions", "Deemed Refusal", "TPN - 22", "TPN - 21", "TPN - 18.1", "Reg 3", "Reg 4", "Reg 5", "s. 43", "Other"]; } if (reviewType === "Investigation") { - return ["Other"] + return ["Other"]; } return ["Adequate search","Extension", "Fee Amount", "Fee Waiver", "Duty to Assist", "Application of Exceptions", "Deemed Refusal", "TPN - 22", "TPN - 21", "TPN - 18.1", "Reg 3", "Reg 4", "Reg 5", "s. 43", "Other"]; } - const reasons = filterReasonOptions(oipc.reviewType) + const reasons = filterReasonOptions(oipc.reviewType); return ( <> From d745a3e6c338abc31ae55eca56c21359f869acbf Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Mon, 20 Nov 2023 15:58:39 -0800 Subject: [PATCH 017/238] Backend changes for oipcreview --- .../request_api/models/FOIMinistryRequests.py | 7 +++++-- .../request_api/models/FOIRawRequests.py | 3 ++- .../request_api/services/dashboardservice.py | 4 ++++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index dfb5cfbf5..7f203d8d0 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -364,7 +364,7 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us if(len(filterfields) > 0 and keyword is not None): filtercondition = [] - if(keyword != "restricted"): + if(keyword != "restricted" and keyword.lower() != "oipc"): for field in filterfields: filtercondition.append(FOIMinistryRequest.findfield(field, iaoassignee, ministryassignee).ilike('%'+keyword+'%')) else: @@ -372,6 +372,8 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us filtercondition.append(FOIRestrictedMinistryRequest.isrestricted == True) else: filtercondition.append(ministry_restricted_requests.isrestricted == True) + if (keyword.lower() == "oipc"): + filtercondition.append(FOIMinistryRequest.isoipcreview == True) intakesorting = case([ (and_(FOIMinistryRequest.assignedto == None, FOIMinistryRequest.assignedgroup == 'Intake Team'), # Unassigned requests first @@ -488,7 +490,8 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us extensions, FOIRestrictedMinistryRequest.isrestricted.label('isiaorestricted'), ministry_restricted_requests.isrestricted.label('isministryrestricted'), - SubjectCode.name.label('subjectcode') + SubjectCode.name.label('subjectcode'), + FOIMinistryRequest.isoipcreview.label('isoipcreview') ] basequery = _session.query( diff --git a/request-management-api/request_api/models/FOIRawRequests.py b/request-management-api/request_api/models/FOIRawRequests.py index 9a0169647..cedb898b5 100644 --- a/request-management-api/request_api/models/FOIRawRequests.py +++ b/request-management-api/request_api/models/FOIRawRequests.py @@ -570,7 +570,8 @@ def getbasequery(cls, additionalfilter=None, userid=None, isiaorestrictedfileman literal(None).label('extensions'), isiaorestricted, literal(None).label('isministryrestricted'), - subjectcode + subjectcode, + literal(None).label('isoipcreview') ] basequery = _session.query(*selectedcolumns).join(subquery_maxversion, and_(*joincondition)).join(FOIAssignee, FOIAssignee.username == FOIRawRequest.assignedto, isouter=True) diff --git a/request-management-api/request_api/services/dashboardservice.py b/request-management-api/request_api/services/dashboardservice.py index ba2f913d1..5a89ac3c6 100644 --- a/request-management-api/request_api/services/dashboardservice.py +++ b/request-management-api/request_api/services/dashboardservice.py @@ -50,6 +50,8 @@ def __preparefoirequestinfo(self, request, receiveddate, receiveddateuf, idnumbe baserequestinfo.update({'onBehalfFirstName': request.onBehalfFirstName}) baserequestinfo.update({'onBehalfLastName': request.onBehalfLastName}) baserequestinfo.update({'requestPageCount': request.requestPageCount}) + isoipcreview = request.isoipcreview if request.isoipcreview == True else False + baserequestinfo.update({'isoipcreview': isoipcreview}) return baserequestinfo def __preparebaserequestinfo(self, id, requesttype, status, receiveddate, receiveddateuf, assignedgroup, assignedto, idnumber, axisrequestid, version, description, fromdate, todate): @@ -148,6 +150,8 @@ def getministryrequestqueuepagination (self, groups=None, page=1, size=10, sorti isministryrestricted = request.isministryrestricted if request.isministryrestricted == True else False _openrequest.update({'isministryrestricted': isministryrestricted}) + isoipcreview = request.isoipcreview if request.isoipcreview == True else False + _openrequest.update({'isoipcreview': isoipcreview}) requestqueue.append(_openrequest) meta = { From 59842f081d3bcb542c01e8718796570c8728a348 Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Mon, 20 Nov 2023 15:59:02 -0800 Subject: [PATCH 018/238] Frontend changes for OIPC review --- .../components/FOI/Dashboard/IAO/columns.js | 26 +++++++----- .../FOI/Dashboard/Ministry/Queue.js | 16 ++++--- .../components/FOI/Dashboard/dashboard.scss | 21 +++++++++- .../src/components/FOI/Dashboard/utils.js | 42 ++++++++++++++++++- 4 files changed, 84 insertions(+), 21 deletions(-) diff --git a/forms-flow-web/src/components/FOI/Dashboard/IAO/columns.js b/forms-flow-web/src/components/FOI/Dashboard/IAO/columns.js index 4cb4166be..213b3dd1d 100644 --- a/forms-flow-web/src/components/FOI/Dashboard/IAO/columns.js +++ b/forms-flow-web/src/components/FOI/Dashboard/IAO/columns.js @@ -5,6 +5,7 @@ import { // onBehalfFullName, displayIcon, displayHeaderIcon, + displayQueueFlagIcons, cellTooltipRender } from "../utils"; import { @@ -15,6 +16,15 @@ import { } from "../../../../helper/FOI/helper"; const ProcessingTeamColumns = [ + { + field: "flags", + // renderHeader: displayHeaderIcon, + headerName: "FLAGS", + headerAlign: "left", + renderCell: displayQueueFlagIcons, + // cellClassName: 'foi-dashboard-', + // flex: 1, + }, { field: "axisRequestId", headerName: "ID NUMBER", @@ -89,12 +99,10 @@ const ProcessingTeamColumns = [ const IntakeTeamColumns = [ { - field: "isiaorestricted", - renderHeader: displayHeaderIcon, + field: "flags", + headerName: "FLAGS", headerAlign: "left", - renderCell:displayIcon, - cellClassName: 'foi-dashboard-restricted', - width: 60, + renderCell: displayQueueFlagIcons, }, { field: "axisRequestId", @@ -161,12 +169,10 @@ const IntakeTeamColumns = [ const FlexTeamColumns = [ { - field: "isiaorestricted", - renderHeader: displayHeaderIcon, + field: "flags", + headerName: "FLAGS", headerAlign: "left", - renderCell:displayIcon, - cellClassName: 'foi-dashboard-restricted', - width: 60, + renderCell: displayQueueFlagIcons, }, { field: "axisRequestId", diff --git a/forms-flow-web/src/components/FOI/Dashboard/Ministry/Queue.js b/forms-flow-web/src/components/FOI/Dashboard/Ministry/Queue.js index 7f775e9bb..33980929a 100644 --- a/forms-flow-web/src/components/FOI/Dashboard/Ministry/Queue.js +++ b/forms-flow-web/src/components/FOI/Dashboard/Ministry/Queue.js @@ -6,7 +6,7 @@ import { useDispatch, useSelector } from "react-redux"; import { push } from "connected-react-router"; import { fetchFOIMinistryRequestListByPage } from "../../../../apiManager/services/FOI/foiRequestServices"; import Loading from "../../../../containers/Loading"; -import { debounce, ClickableChip, displayIconMinistry, displayHeaderIcon, cellTooltipRender } from "../utils"; +import { debounce, ClickableChip, displayRestrictedIconMinistry, displayOipcReviewIconMinistry, displayPhasedReleaseIconMinistry, displayHeaderIcon, cellTooltipRender, displayQueueFlagIcons } from "../utils"; import Grid from "@mui/material/Grid"; import Stack from "@mui/material/Stack"; import SearchIcon from "@material-ui/icons/Search"; @@ -112,6 +112,12 @@ const Queue = ({ userDetail, tableInfo }) => { } const columns = React.useRef([ + { + field: "flags", + headerName: "FLAGS", + headerAlign: "left", + renderCell: displayQueueFlagIcons, + }, { field: "axisRequestId", headerName: "ID NUMBER", @@ -165,14 +171,6 @@ const Queue = ({ userDetail, tableInfo }) => { width: 0, hide: true, renderCell: (_params) => , - }, - { - field: "isministryrestricted", - renderHeader: displayHeaderIcon, - headerAlign: "left", - renderCell: displayIconMinistry, - cellClassName: 'foi-dashboard-restricted', - flex: 1, } ]); diff --git a/forms-flow-web/src/components/FOI/Dashboard/dashboard.scss b/forms-flow-web/src/components/FOI/Dashboard/dashboard.scss index 92123f7a5..1cf6da99d 100644 --- a/forms-flow-web/src/components/FOI/Dashboard/dashboard.scss +++ b/forms-flow-web/src/components/FOI/Dashboard/dashboard.scss @@ -246,9 +246,28 @@ nav.MuiPagination-root { padding-right: 15px !important; } -.foi-dashboard-restricted { +.dashboard-flag-restricted { font-size: 10px; color: #A0192F; + padding: 2px; +} + +.dashboard-flag-oipcreview { + font-size: 10px; + color: #fa7c16; + padding: 2px; +} + +.dashboard-flag-phasedrelease { + font-size: 10px; + color: #9207b7; + padding: 2px; +} + +.dashboard-flag-placeholder { + font-size: 10px; + color: #c1bfbf; + padding: 2px; } .table-cell-truncate { diff --git a/forms-flow-web/src/components/FOI/Dashboard/utils.js b/forms-flow-web/src/components/FOI/Dashboard/utils.js index 0bb6d1a6a..a363e303e 100644 --- a/forms-flow-web/src/components/FOI/Dashboard/utils.js +++ b/forms-flow-web/src/components/FOI/Dashboard/utils.js @@ -219,9 +219,49 @@ export const displayIconMinistry = (params) => { ); }; +export const displayQueueFlagIcons = (params) => { + let restricted = + + if (params?.row?.isiaorestricted || params?.row?.isministryrestricted) { + restricted = + Restricted +
+ }> + + + } else { + restricted = + } + + const oipcreview = params?.row?.isoipcreview ? + + OIPC +
+ }> + : + + + const phasedrelease = params?.row?.isphasedrelease ? + + Phased Release + + }> + : + + + return
+ {restricted} + {oipcreview} + {/* {phasedrelease} */} +
+} + export const displayHeaderIcon = (params) => { return ( - + ); }; From e00f1b7a5fb8e8abba7ffb680a539fa30af371dd Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Mon, 20 Nov 2023 16:00:38 -0800 Subject: [PATCH 019/238] State mgmt code fixes --- .../OIPCDetails/OIPCDetailsList.jsx | 4 +- .../FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 47 ++++++++++++++----- 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx index e3c8ac499..5d5e4bdf1 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx @@ -6,7 +6,7 @@ import { faTrash } from '@fortawesome/free-solid-svg-icons'; const OIPCDetailsList = (props) => { const {oipcData, removeOIPC, updateOIPC} = props; - console.log("TEST THIS", oipcData); + console.log("ARRAY", oipcData); const OIPCItems = oipcData?.map((oipcObj, index) => { return ( @@ -16,7 +16,7 @@ const OIPCDetailsList = (props) => { - + {index !== (oipcData.length - 1) && } ); diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index dc1e6ba8e..1c0212009 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -7,11 +7,13 @@ const OIPCItem = (props) => { const {oipcObj, updateOIPC} = props; const [oipc, setOipc] = useState({ + id: oipcObj?.id, oipcNumber: oipcObj?.oipcNumber, reviewType: oipcObj?.reviewType, reason: oipcObj?.reason, status: oipcObj?.status, isInquiry: oipcObj?.isInquiry, + inquiryDate: null, receivedDate: oipcObj?.receivedDate, investigator: oipcObj?.investigator, outcome: oipcObj?.outcome, @@ -22,34 +24,55 @@ const OIPCItem = (props) => { console.log(oipcObj); const handleReviewType = (value) => { - updateOIPC({...oipc, reviewType: value, reason: ""}); + const newOIPCObj = oipc; + newOIPCObj.reviewType = value; + newOIPCObj.reason = ""; + updateOIPC(newOIPCObj); } const handleOIPCNumber = (value) => { - updateOIPC({...oipc, oipcNumber: value}); + const newOIPCObj = oipc; + newOIPCObj.oipcNumber = value; + updateOIPC(newOIPCObj); } const handleReceivedDate = (value) => { - updateOIPC({...oipc, receivedDate: value}); + const newOIPCObj = oipc; + newOIPCObj.receivedDate = value; + updateOIPC(newOIPCObj); } const handleReason = (value) => { - updateOIPC({...oipc, reason: value}); + const newOIPCObj = oipc; + newOIPCObj.reason = value; + updateOIPC(newOIPCObj); } const handleStatus = (value) => { - updateOIPC({...oipc, status: value}); + const newOIPCObj = oipc; + newOIPCObj.status = value; + updateOIPC(newOIPCObj); } const handleInvestiagtor = (value) => { - updateOIPC({...oipc, investigator: value}); + const newOIPCObj = oipc; + newOIPCObj.investigator = value; + updateOIPC(newOIPCObj); } const handleOutcome = (value) => { - updateOIPC({...oipc, outcome: value}); + const newOIPCObj = oipc; + newOIPCObj.outcome = value; + updateOIPC(newOIPCObj); } const handleInquiry = (value) => { - updateOIPC({...oipc, isInquiry: value}); + const newOIPCObj = oipc; + newOIPCObj.isInquiry = value; + updateOIPC(newOIPCObj); } const handleJudicalReview = (value) => { - updateOIPC({...oipc, isJudicalReview: value}); + const newOIPCObj = oipc; + newOIPCObj.isJudicalReview = value; + updateOIPC(newOIPCObj); } const handleSubsequentAppeal = (value) => { - updateOIPC({...oipc, isSubAppeal: value}); + const newOIPCObj = oipc; + newOIPCObj.isSubAppeal = value; + updateOIPC(newOIPCObj); } //REFACTOR THIS!!! const filterReasonOptions = (reviewType) => { @@ -60,12 +83,12 @@ const OIPCItem = (props) => { return ["Application of Exceptions", "Deemed Refusal", "TPN - 22", "TPN - 21", "TPN - 18.1", "Reg 3", "Reg 4", "Reg 5", "s. 43", "Other"]; } if (reviewType === "Investigation") { - return ["Other"]; + return ["Other"] } return ["Adequate search","Extension", "Fee Amount", "Fee Waiver", "Duty to Assist", "Application of Exceptions", "Deemed Refusal", "TPN - 22", "TPN - 21", "TPN - 18.1", "Reg 3", "Reg 4", "Reg 5", "s. 43", "Other"]; } - const reasons = filterReasonOptions(oipc.reviewType); + const reasons = filterReasonOptions(oipc.reviewType) return ( <> From a37f06a21d4c8640193cf73dca3959bd50299b3c Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Tue, 21 Nov 2023 09:48:09 -0800 Subject: [PATCH 020/238] Remove unused imports --- forms-flow-web/src/components/FOI/Dashboard/Ministry/Queue.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forms-flow-web/src/components/FOI/Dashboard/Ministry/Queue.js b/forms-flow-web/src/components/FOI/Dashboard/Ministry/Queue.js index 33980929a..a8b92a7ac 100644 --- a/forms-flow-web/src/components/FOI/Dashboard/Ministry/Queue.js +++ b/forms-flow-web/src/components/FOI/Dashboard/Ministry/Queue.js @@ -6,7 +6,7 @@ import { useDispatch, useSelector } from "react-redux"; import { push } from "connected-react-router"; import { fetchFOIMinistryRequestListByPage } from "../../../../apiManager/services/FOI/foiRequestServices"; import Loading from "../../../../containers/Loading"; -import { debounce, ClickableChip, displayRestrictedIconMinistry, displayOipcReviewIconMinistry, displayPhasedReleaseIconMinistry, displayHeaderIcon, cellTooltipRender, displayQueueFlagIcons } from "../utils"; +import { debounce, ClickableChip, cellTooltipRender, displayQueueFlagIcons } from "../utils"; import Grid from "@mui/material/Grid"; import Stack from "@mui/material/Stack"; import SearchIcon from "@material-ui/icons/Search"; From 0181105e732ae1d2543de481f028f512326f486f Mon Sep 17 00:00:00 2001 From: "sumathi.thirumani" Date: Tue, 21 Nov 2023 16:25:39 -0800 Subject: [PATCH 021/238] Changes to include descriptive value for masterdata + new date inlusion. --- .../versions/455a24da8c58_oipc_txn_changes.py | 6 ++++++ .../request_api/models/FOIRequestOIPC.py | 18 +++++++++++++----- .../request_api/schemas/foirequestwrapper.py | 3 ++- .../foirequest/requestservicebuilder.py | 2 ++ .../foirequest/requestservicegetter.py | 6 ++++++ 5 files changed, 29 insertions(+), 6 deletions(-) diff --git a/request-management-api/migrations/versions/455a24da8c58_oipc_txn_changes.py b/request-management-api/migrations/versions/455a24da8c58_oipc_txn_changes.py index 764909fc4..20f8ab5c5 100644 --- a/request-management-api/migrations/versions/455a24da8c58_oipc_txn_changes.py +++ b/request-management-api/migrations/versions/455a24da8c58_oipc_txn_changes.py @@ -33,11 +33,17 @@ def upgrade(): sa.Column('isjudicialreview', sa.Boolean(), nullable=True), sa.Column('issubsequentappeal', sa.Boolean(), nullable=True), sa.Column('inquiryattributes', sa.JSON, nullable=True), + sa.Column('receiveddate', sa.Date(), nullable=True), + sa.Column('closeddate', sa.Date(), nullable=True), sa.Column('created_at', sa.DateTime(), nullable=False), sa.Column('createdby', sa.String(length=120), nullable=False), sa.Column('updated_at', sa.DateTime(), nullable=True), sa.Column('updatedby', sa.String(length=120), nullable=True), sa.ForeignKeyConstraint(['foiministryrequest_id', 'foiministryrequestversion_id'], ['FOIMinistryRequests.foiministryrequestid', 'FOIMinistryRequests.version'], ), + sa.ForeignKeyConstraint(['reviewtypeid'], ['OIPCReviewTypes.reviewtypeid']), + sa.ForeignKeyConstraint(['reasonid'], ['OIPCReasons.reasonid']), + sa.ForeignKeyConstraint(['statusid'], ['OIPCStatuses.statusid']), + sa.ForeignKeyConstraint(['outcomeid'], ['OIPCOutcomes.outcomeid']), sa.PrimaryKeyConstraint('oipcid') ) # ### end Alembic commands ### diff --git a/request-management-api/request_api/models/FOIRequestOIPC.py b/request-management-api/request_api/models/FOIRequestOIPC.py index 1aacce9fd..a68407b9f 100644 --- a/request-management-api/request_api/models/FOIRequestOIPC.py +++ b/request-management-api/request_api/models/FOIRequestOIPC.py @@ -19,15 +19,21 @@ class FOIRequestOIPC(db.Model): foiministryrequest_id =db.Column(db.Integer, db.ForeignKey('FOIMinistryRequests.foiministryrequestid')) foiministryrequestversion_id =db.Column(db.Integer, db.ForeignKey('FOIMinistryRequests.version')) oipcno = db.Column(db.String(120), unique=False, nullable=True) - reviewtypeid = db.Column(db.Integer, unique=False, nullable=False) - reasonid = db.Column(db.Integer, unique=False, nullable=False) - statusid = db.Column(db.Integer, unique=False, nullable=True) - outcomeid = db.Column(db.Integer, unique=False, nullable=True) + reviewtypeid = db.Column(db.Integer,ForeignKey('OIPCReviewTypes.reviewtypeid')) + reviewtype = relationship("OIPCReviewTypes",backref=backref("OIPCReviewTypes"),uselist=False) + reasonid = db.Column(db.Integer,ForeignKey('OIPCReasons.reasonid')) + reason = relationship("OIPCReasons",backref=backref("OIPCReasons"),uselist=False) + statusid = db.Column(db.Integer,ForeignKey('OIPCStatuses.statusid')) + status = relationship("OIPCStatuses",backref=backref("OIPCStatuses"),uselist=False) + outcomeid = db.Column(db.Integer,ForeignKey('OIPCOutcomes.outcomeid')) + outcome = relationship("OIPCOutcomes",backref=backref("OIPCOutcomes"),uselist=False) isinquiry = db.Column(db.Boolean, unique=False, nullable=True) inquiryattributes = db.Column(JSON, unique=False, nullable=True) isjudicialreview = db.Column(db.Boolean, unique=False, nullable=True) issubsequentappeal = db.Column(db.Boolean, unique=False, nullable=True) investigator = db.Column(db.String(500), unique=False, nullable=True) + receiveddate = db.Column(db.Date, nullable=True) + closeddate = db.Column(db.Date, nullable=True) created_at = db.Column(db.DateTime, default=datetime.now) createdby = db.Column(db.String(120), unique=False, nullable=False) updated_at = db.Column(db.DateTime, nullable=True) @@ -44,4 +50,6 @@ def getoipc(cls,ministryrequestid,ministryrequestversion): class FOIRequestOIPCSchema(ma.Schema): class Meta: - fields = ('oipcid', 'version', 'ministryrequestid', 'investigator','ministryversion','oipcno','reviewtypeid','reasonid','statusid','outcomeid','isinquiry','inquiryattributes','isjudicialreview','issubsequentappeal','isactive','created_at','createdby','updated_at','updatedby') \ No newline at end of file + fields = ('oipcid', 'version', 'ministryrequestid', 'investigator','ministryversion','oipcno','reviewtypeid','reasonid','statusid','outcomeid','isinquiry','inquiryattributes','isjudicialreview', + 'issubsequentappeal','isactive','receiveddate','closeddate','created_at','createdby','updated_at','updatedby', + 'reviewtype.name', 'reason.name', 'status.name', 'outcome.name') \ No newline at end of file diff --git a/request-management-api/request_api/schemas/foirequestwrapper.py b/request-management-api/request_api/schemas/foirequestwrapper.py index 38a9ab1dc..186f226fb 100644 --- a/request-management-api/request_api/schemas/foirequestwrapper.py +++ b/request-management-api/request_api/schemas/foirequestwrapper.py @@ -78,7 +78,8 @@ class Meta: # pylint: disable=too-few-public-methods isjudicialreview = fields.Bool(data_key="isjudicialreview") issubsequentappeal = fields.Bool(data_key="issubsequentappeal") inquiryattributes = fields.Nested(FOIOIPCInquirySchema, data_key="inquiryattributes", allow_none=True) - + receiveddate = fields.Str(data_key="receiveddate",allow_none=True) + closeddate = fields.Str(data_key="closeddate",allow_none=True) class FOIRequestWrapperSchema(Schema): diff --git a/request-management-api/request_api/services/foirequest/requestservicebuilder.py b/request-management-api/request_api/services/foirequest/requestservicebuilder.py index 790cbc540..1e89300e4 100644 --- a/request-management-api/request_api/services/foirequest/requestservicebuilder.py +++ b/request-management-api/request_api/services/foirequest/requestservicebuilder.py @@ -149,6 +149,8 @@ def prepareoipc(self, requestschema, ministryrequestid, version, userid): oipcreview.isjudicialreview = oipc["isjudicialreview"] oipcreview.issubsequentappeal = oipc["issubsequentappeal"] oipcreview.issubsequentappeal = oipc["issubsequentappeal"] + oipcreview.receiveddate = oipc["receiveddate"] + oipcreview.closeddate = oipc["closeddate"] oipcreview.isactive = True if oipc["isinquiry"] == True: oipcreview.inquiryattributes = oipc["inquiryattributes"] diff --git a/request-management-api/request_api/services/foirequest/requestservicegetter.py b/request-management-api/request_api/services/foirequest/requestservicegetter.py index d3fedf68b..31ad6750c 100644 --- a/request-management-api/request_api/services/foirequest/requestservicegetter.py +++ b/request-management-api/request_api/services/foirequest/requestservicegetter.py @@ -219,15 +219,21 @@ def getoipcdetails(self, ministryrequestid, ministryrequestversion): oipc = { "oipcid": entry["oipcid"], "reviewtypeid": entry["reviewtypeid"], + "reviewetype": entry["reviewtype.name"], "reasonid": entry["reasonid"], + "reason": entry["reason.name"], "statusid": entry["statusid"], + "status":entry["status.name"], "outcomeid": entry["outcomeid"], + "outcome": entry["outcome.name"], "investigator": entry["investigator"], "isinquiry": entry["isinquiry"], "isjudicialreview": entry["isjudicialreview"], "issubsequentappeal": entry["issubsequentappeal"], "inquiryattributes": entry["inquiryattributes"], "createdby": entry["createdby"], + "receiveddate" : parse(entry["receiveddate"]).strftime('%b, %d %Y') if entry["receiveddate"] is not None else '', + "closeddate": parse(entry["closeddate"]).strftime('%b, %d %Y') if entry["closeddate"] is not None else '', "created_at": parse(entry["created_at"]).strftime(self.__genericdateformat()) } oipcdetails.append(oipc) From 35c5a001de863949cf3999049d7a931d5bf25563 Mon Sep 17 00:00:00 2001 From: "sumathi.thirumani" Date: Tue, 21 Nov 2023 17:32:35 -0800 Subject: [PATCH 022/238] Changes to include descriptive value for inquiry outcome --- .../request_api/schemas/foirequestwrapper.py | 2 +- .../services/foirequest/requestservicegetter.py | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/request-management-api/request_api/schemas/foirequestwrapper.py b/request-management-api/request_api/schemas/foirequestwrapper.py index 186f226fb..967a67a14 100644 --- a/request-management-api/request_api/schemas/foirequestwrapper.py +++ b/request-management-api/request_api/schemas/foirequestwrapper.py @@ -61,7 +61,7 @@ class Meta: # pylint: disable=too-few-public-methods unknown = EXCLUDE inquirydate = fields.Str(data_key="inquirydate",allow_none=True) orderno = fields.Str(data_key="orderno",allow_none=True) - inquiryoutcome = fields.Str(data_key="outcome",allow_none=True) + inquiryoutcome = fields.Int(data_key="inquiryoutcome",allow_none=True) class FOIMinistryRequestOIPCSchema(Schema): class Meta: # pylint: disable=too-few-public-methods diff --git a/request-management-api/request_api/services/foirequest/requestservicegetter.py b/request-management-api/request_api/services/foirequest/requestservicegetter.py index 31ad6750c..16beb77da 100644 --- a/request-management-api/request_api/services/foirequest/requestservicegetter.py +++ b/request-management-api/request_api/services/foirequest/requestservicegetter.py @@ -9,6 +9,7 @@ from request_api.models.FOIMinistryRequestSubjectCodes import FOIMinistryRequestSubjectCode from request_api.models.FOIRestrictedMinistryRequests import FOIRestrictedMinistryRequest from request_api.models.FOIRequestOIPC import FOIRequestOIPC +from request_api.services.oipcservice import oipcservice from dateutil.parser import parse from request_api.services.cfrfeeservice import cfrfeeservice from request_api.services.paymentservice import paymentservice @@ -214,6 +215,7 @@ def getdivisions(self, ministrydivisions): def getoipcdetails(self, ministryrequestid, ministryrequestversion): oipcdetails = [] _oipclist = FOIRequestOIPC.getoipc(ministryrequestid, ministryrequestversion) + inquiryoutcomes = oipcservice().getinquiryoutcomes() if _oipclist is not None: for entry in _oipclist: oipc = { @@ -230,7 +232,7 @@ def getoipcdetails(self, ministryrequestid, ministryrequestversion): "isinquiry": entry["isinquiry"], "isjudicialreview": entry["isjudicialreview"], "issubsequentappeal": entry["issubsequentappeal"], - "inquiryattributes": entry["inquiryattributes"], + "inquiryattributes": self.formatinquiryattribute(entry["inquiryattributes"], inquiryoutcomes), "createdby": entry["createdby"], "receiveddate" : parse(entry["receiveddate"]).strftime('%b, %d %Y') if entry["receiveddate"] is not None else '', "closeddate": parse(entry["closeddate"]).strftime('%b, %d %Y') if entry["closeddate"] is not None else '', @@ -239,7 +241,13 @@ def getoipcdetails(self, ministryrequestid, ministryrequestversion): oipcdetails.append(oipc) return oipcdetails - + def formatinquiryattribute(self, inquiryattribute, inquiryoutcomes): + if inquiryattribute not in (None, {}): + for outcome in inquiryoutcomes: + if inquiryattribute["inquiryoutcome"] == outcome["inquiryoutcomeid"]: + inquiryattribute["inquiryoutcomename"] = outcome["name"] + return inquiryattribute + def getonholdtransition(self, foiministryrequestid): onholddate = None From 214cc23c653487d7a25df97ad90e590e46878b44 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Tue, 21 Nov 2023 17:45:22 -0800 Subject: [PATCH 023/238] BE integration work --- .../src/actions/FOI/foiActionConstants.js | 4 + .../src/actions/FOI/foiRequestActions.js | 21 +++ .../src/apiManager/endpoints/index.js | 4 + .../services/FOI/foiMasterDataServices.js | 69 +++++++++ .../components/FOI/FOIRequest/FOIRequest.js | 9 +- .../OIPCDetails/AdditionalFields.jsx | 0 .../FOI/FOIRequest/OIPCDetails/Index.jsx | 47 +++--- .../OIPCDetails/MandatoryFields.jsx | 0 .../OIPCDetails/OIPCDetailsList.jsx | 1 - .../FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 134 ++++++++++++------ .../src/modules/FOI/foiRequestsReducer.js | 9 ++ .../foirequest/requestservicegetter.py | 1 + 12 files changed, 227 insertions(+), 72 deletions(-) delete mode 100644 forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/AdditionalFields.jsx delete mode 100644 forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/MandatoryFields.jsx diff --git a/forms-flow-web/src/actions/FOI/foiActionConstants.js b/forms-flow-web/src/actions/FOI/foiActionConstants.js index beaca7433..ef0bc6dac 100644 --- a/forms-flow-web/src/actions/FOI/foiActionConstants.js +++ b/forms-flow-web/src/actions/FOI/foiActionConstants.js @@ -89,6 +89,10 @@ const FOI_ACTION_CONSTANTS = { "FOI_PDF_STITCHED_STATUS_FOR_RESPONSEPACKAGE", FOI_PDF_STITCHED_RECORD_FOR_RESPONSEPACKAGE: "FOI_PDF_STITCHED_RECORD_FOR_RESPONSEPACKAGE", + + OIPC_OUTCOMES: "OIPC_OUTCOMES", + OIPC_STATUSES: "OIPC_STATUSES", + OIPC_REVIEWTYPES: "OIPC_REVIEWTYPES", }; export default FOI_ACTION_CONSTANTS; diff --git a/forms-flow-web/src/actions/FOI/foiRequestActions.js b/forms-flow-web/src/actions/FOI/foiRequestActions.js index 8cb6826c1..46ffcf494 100644 --- a/forms-flow-web/src/actions/FOI/foiRequestActions.js +++ b/forms-flow-web/src/actions/FOI/foiRequestActions.js @@ -425,3 +425,24 @@ export const setConversionFormats = (data) => (dispatch) => { payload: data, }); }; + +export const setOIPCOutcomes = (data) => (dispatch) => { + dispatch({ + type: FOI_ACTION_CONSTANTS.OIPC_OUTCOMES, + payload: data, + }); +}; + +export const setOIPCStatuses = (data) => (dispatch) => { + dispatch({ + type: FOI_ACTION_CONSTANTS.OIPC_STATUSES, + payload: data, + }); +}; + +export const setOIPCReviewtypes = (data) => (dispatch) => { + dispatch({ + type: FOI_ACTION_CONSTANTS.OIPC_REVIEWTYPES, + payload: data, + }); +}; diff --git a/forms-flow-web/src/apiManager/endpoints/index.js b/forms-flow-web/src/apiManager/endpoints/index.js index 111ee62ec..60762afca 100644 --- a/forms-flow-web/src/apiManager/endpoints/index.js +++ b/forms-flow-web/src/apiManager/endpoints/index.js @@ -133,5 +133,9 @@ const API = { FOI_DOWNLOAD_RECORDS_FOR_RESPONSEPACKAGE: `${FOI_BASE_API_URL}/api/foirecord//ministryrequest//download/responsepackage`, FOI_PDF_STITCH_STATUS_FOR_RESPONSEPACKAGE: `${FOI_BASE_API_URL}/api/foirecord//ministryrequest//responsepackage/pdfstitchjobstatus`, + + FOI_GET_OIPC_OUTCOMES: `${FOI_BASE_API_URL}/api/foiflow/oipc/outcomes`, + FOI_GET_OIPC_STATUSES: `${FOI_BASE_API_URL}/api/foiflow/oipc/statuses`, + FOI_GET_OIPC_REVIEWTYPES: `${FOI_BASE_API_URL}/api/foiflow/oipc/reviewtypes`, }; export default API; diff --git a/forms-flow-web/src/apiManager/services/FOI/foiMasterDataServices.js b/forms-flow-web/src/apiManager/services/FOI/foiMasterDataServices.js index b8eb8d385..16bd8476b 100644 --- a/forms-flow-web/src/apiManager/services/FOI/foiMasterDataServices.js +++ b/forms-flow-web/src/apiManager/services/FOI/foiMasterDataServices.js @@ -22,6 +22,9 @@ import { setFOISubjectCodeList, setCommentTagListLoader, setFOIAdminProgramAreaList, + setOIPCOutcomes, + setOIPCStatuses, + setOIPCReviewtypes, } from "../../../actions/FOI/foiRequestActions"; import { fnDone, catchError } from "./foiServicesUtil"; import UserService from "../../../services/UserService"; @@ -508,4 +511,70 @@ import { }); }; }; + + export const fetchOIPCOutcomes = () => { + return (dispatch) => { + httpGETRequest(API.FOI_GET_OIPC_OUTCOMES, {}, UserService.getToken()) + .then((res) => { + if (res.data) { + const oipcOutcomes = res.data; + dispatch(setOIPCOutcomes(oipcOutcomes)); + dispatch(setFOILoader(false)); + } else { + console.log("Error while fetching OIPC outcomes master data", res); + dispatch(serviceActionError(res)); + dispatch(setFOILoader(false)); + } + }) + .catch((error) => { + console.log("Error while fetching OIPC outcomes master data", error); + dispatch(serviceActionError(error)); + dispatch(setFOILoader(false)); + }); + }; + }; + + export const fetchOIPCStatuses = () => { + return (dispatch) => { + httpGETRequest(API.FOI_GET_OIPC_STATUSES, {}, UserService.getToken()) + .then((res) => { + if (res.data) { + const oipcStatuses = res.data; + dispatch(setOIPCStatuses(oipcStatuses)); + dispatch(setFOILoader(false)); + } else { + console.log("Error while fetching OIPC statuses master data", res); + dispatch(serviceActionError(res)); + dispatch(setFOILoader(false)); + } + }) + .catch((error) => { + console.log("Error while fetching OIPC statuses master data", error); + dispatch(serviceActionError(error)); + dispatch(setFOILoader(false)); + }); + }; + }; + + export const fetchOIPCReviewtypes = () => { + return (dispatch) => { + httpGETRequest(API.FOI_GET_OIPC_REVIEWTYPES, {}, UserService.getToken()) + .then((res) => { + if (res.data) { + const oipcReviewtypes = res.data; + dispatch(setOIPCReviewtypes(oipcReviewtypes)); + dispatch(setFOILoader(false)); + } else { + console.log("Error while fetching OIPC reviewtypes master data", res); + dispatch(serviceActionError(res)); + dispatch(setFOILoader(false)); + } + }) + .catch((error) => { + console.log("Error while fetching OIPC reviewtypes master data", error); + dispatch(serviceActionError(error)); + dispatch(setFOILoader(false)); + }); + }; + }; \ No newline at end of file diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index 10c384bc8..2142892cf 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -24,6 +24,9 @@ import { fetchFOIMinistryAssignedToList, fetchFOISubjectCodeList, fetchFOIPersonalDivisionsAndSections, + fetchOIPCOutcomes, + fetchOIPCStatuses, + fetchOIPCReviewtypes, } from "../../../apiManager/services/FOI/foiMasterDataServices"; import { fetchFOIRequestDetailsWrapper, @@ -293,6 +296,10 @@ const FOIRequest = React.memo(({ userDetail }) => { dispatch(fetchFOIDeliveryModeList()); dispatch(fetchFOISubjectCodeList()); dispatch(fetchClosingReasonList()); + + dispatch(fetchOIPCOutcomes()); + dispatch(fetchOIPCStatuses()); + dispatch(fetchOIPCReviewtypes()); if (bcgovcode) dispatch(fetchFOIMinistryAssignedToList(bcgovcode)); }, [requestId, ministryId, comment, attachments]); @@ -1211,7 +1218,7 @@ const FOIRequest = React.memo(({ userDetail }) => { )} {showOIPCDetails && ( )} diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/AdditionalFields.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/AdditionalFields.jsx deleted file mode 100644 index e69de29bb..000000000 diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx index adcffe4a1..d9fa50c4b 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx @@ -10,19 +10,18 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faCirclePlus } from '@fortawesome/free-solid-svg-icons'; const OIPCDetails = (props) => { - //Local State - const createOIPCId = (oipcData) => { - if (oipcData.length > 0) { - return oipcData.map((item, index) => { - item.id = index; - return item; - }); - } - } - const [oipcData, setOipcData] = useState(createOIPCId([ - { oipcNumber: "F23-12345", reviewType: "Complaint", reason: "Extension", status: "Inquiry", isInquiry: false, inquiryDate: null, receivedDate: "2022-05-08", investigator: "Filip Forsberg", outcome: "Withdrawn", isJudicalReview: false, isSubAppeal: false }, - { oipcNumber: "F23-12346", reviewType: "Review", reason: "Other", status: "Mediation", isInquiry: false, inquiryDate: null, receivedDate: "2022-09-08", investigator: "Peter Forsberg", outcome: "Closed", isJudicalReview: false, isSubAppeal: true }, - ])); + const { oipcDetails } = props; + + //Local State + const createOIPCId = (oipcData) => { + if (oipcData.length > 0) { + return oipcData.map((item, index) => { + item.id = index; + return item; + }); + } + } + const [oipcData, setOipcData] = useState(createOIPCId(oipcDetails)); //Styling const useStyles = makeStyles({ @@ -36,22 +35,24 @@ const OIPCDetails = (props) => { } }); const classes = useStyles(); - + //Functions const addOIPC = () => { setOipcData((prev) => { return [...prev, { id: oipcData.length > 0 ? oipcData[oipcData.length - 1].id + 1 : 0, - oipcNumber: "", - reviewType: "", - reason: "", - status: "", - isInquiry: false, - receivedDate: "", + oipcno: "", + reviewtypeid: null, + reasonid: null, + statusid: null, + isinquiry: false, + inquiryattributes: null, + receiveddate: "", + closeddate: "", investigator: "", - outcome: "", - isJudicalReview: false, - isSubAppeal: false + outcomeid: null, + isjudicialreview: false, + issubsequentappeal: false }]; }) } diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/MandatoryFields.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/MandatoryFields.jsx deleted file mode 100644 index e69de29bb..000000000 diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx index 5d5e4bdf1..16e5cdfe6 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx @@ -6,7 +6,6 @@ import { faTrash } from '@fortawesome/free-solid-svg-icons'; const OIPCDetailsList = (props) => { const {oipcData, removeOIPC, updateOIPC} = props; - console.log("ARRAY", oipcData); const OIPCItems = oipcData?.map((oipcObj, index) => { return ( diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index 1c0212009..02ed42071 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -1,52 +1,69 @@ import { TextField, FormControlLabel, MenuItem, Grid, Checkbox } from '@material-ui/core'; import { useState } from "react"; +import { useSelector } from "react-redux"; import { formatDate } from "../../../../helper/FOI/helper"; const OIPCItem = (props) => { const {oipcObj, updateOIPC} = props; + //Local State const [oipc, setOipc] = useState({ id: oipcObj?.id, - oipcNumber: oipcObj?.oipcNumber, - reviewType: oipcObj?.reviewType, - reason: oipcObj?.reason, - status: oipcObj?.status, - isInquiry: oipcObj?.isInquiry, - inquiryDate: null, - receivedDate: oipcObj?.receivedDate, + oipcno: oipcObj?.oipcno, + reviewtypeid: oipcObj?.reviewtypeid, + reasonid: oipcObj?.reasonid, + statusid: oipcObj?.statusid, + isinquiry: oipcObj?.isinquiry, + inquiryattributes: oipcObj?.inquiryattributes, + receiveddate: oipcObj?.receiveddate, + closeddate: oipcObj?.closeddate, investigator: oipcObj?.investigator, - outcome: oipcObj?.outcome, - isJudicalReview: oipcObj?.isJudicalReview, - isSubAppeal: oipcObj?.isSubAppeal, + outcomeid: oipcObj?.outcomeid, + isjudicialreview: oipcObj?.isjudicialreview, + issubsequentappeal: oipcObj?.issubsequentappeal, }); - console.log(oipcObj); + //App State + const oipcOutcomes = useSelector(state=> state.foiRequests.oipcOutcomes); + const oipcStatuses = useSelector(state=> state.foiRequests.oipcStatuses); + const oipcReviewtypes = useSelector(state=> state.foiRequests.oipcReviewtypes); + + console.log(oipc); + console.log(oipcOutcomes) + console.log(oipcStatuses) + console.log(oipcReviewtypes) + //Functions const handleReviewType = (value) => { const newOIPCObj = oipc; - newOIPCObj.reviewType = value; - newOIPCObj.reason = ""; + newOIPCObj.reviewtypeid = value; + newOIPCObj.reasonid = -1; updateOIPC(newOIPCObj); } const handleOIPCNumber = (value) => { const newOIPCObj = oipc; - newOIPCObj.oipcNumber = value; + newOIPCObj.oipcno = value; updateOIPC(newOIPCObj); } const handleReceivedDate = (value) => { const newOIPCObj = oipc; - newOIPCObj.receivedDate = value; + newOIPCObj.receiveddate = value; + updateOIPC(newOIPCObj); + } + const handleClosedDate = (value) => { + const newOIPCObj = oipc; + newOIPCObj.closeddate = value; updateOIPC(newOIPCObj); } const handleReason = (value) => { const newOIPCObj = oipc; - newOIPCObj.reason = value; + newOIPCObj.reasonid = value; updateOIPC(newOIPCObj); } const handleStatus = (value) => { const newOIPCObj = oipc; - newOIPCObj.status = value; + newOIPCObj.statusid = value; updateOIPC(newOIPCObj); } const handleInvestiagtor = (value) => { @@ -56,24 +73,38 @@ const OIPCItem = (props) => { } const handleOutcome = (value) => { const newOIPCObj = oipc; - newOIPCObj.outcome = value; + newOIPCObj.outcomeid = value; updateOIPC(newOIPCObj); } const handleInquiry = (value) => { const newOIPCObj = oipc; - newOIPCObj.isInquiry = value; + newOIPCObj.isinquiry = value; updateOIPC(newOIPCObj); } const handleJudicalReview = (value) => { const newOIPCObj = oipc; - newOIPCObj.isJudicalReview = value; + newOIPCObj.isjudicialreview = value; updateOIPC(newOIPCObj); } const handleSubsequentAppeal = (value) => { const newOIPCObj = oipc; - newOIPCObj.isSubAppeal = value; + newOIPCObj.issubsequentappeal = value; updateOIPC(newOIPCObj); } + const getNameFromId = (attribute, id) => { + if (attribute === "STATUS") { + const status = oipcStatuses.find(status => status.statusid === id); + return status.name; + } + if (attribute === "REVIEW_TYPE") { + const reviewtype = oipcReviewtypes.find(reviewtype => reviewtype.reviewtypeid === id); + return reviewtype.name; + } + if (attribute === "OUTCOME") { + const outcome = oipcOutcomes.find(outcome => outcome.outcomeid === id); + return outcome.name; + } + } //REFACTOR THIS!!! const filterReasonOptions = (reviewType) => { if (reviewType === "Complaint") { @@ -87,7 +118,6 @@ const OIPCItem = (props) => { } return ["Adequate search","Extension", "Fee Amount", "Fee Waiver", "Duty to Assist", "Application of Exceptions", "Deemed Refusal", "TPN - 22", "TPN - 21", "TPN - 18.1", "Reg 3", "Reg 4", "Reg 5", "s. 43", "Other"]; } - const reasons = filterReasonOptions(oipc.reviewType) return ( @@ -99,7 +129,7 @@ const OIPCItem = (props) => { label="OIPC No" variant="outlined" required={true} - value={oipc.oipcNumber} + value={oipc.oipcno} onChange = {(event) => handleOIPCNumber(event.target.value)} InputLabelProps={{ shrink: true }} /> @@ -110,10 +140,10 @@ const OIPCItem = (props) => { label="Received Date" variant="outlined" required={true} - value={oipc.receivedDate} + value={oipc.receiveddate} onChange = {(event) => handleReceivedDate(event.target.value)} InputLabelProps={{ shrink: true }} - InputProps={{inputProps: { max: oipc.receivedDate || formatDate(new Date())} }} + InputProps={{inputProps: { max: oipc.receiveddate || formatDate(new Date())} }} type="date" />
@@ -123,14 +153,14 @@ const OIPCItem = (props) => { select variant="outlined" fullWidth - value={oipc.reviewType} + value={getNameFromId("REVIEW_TYPE", oipc.reviewtypeid)} label="Review Type" onChange={(event) => handleReviewType(event.target.value)} required={true} > - Complaint - Review - Investigation + {oipcReviewtypes.map((reviewtype) => { + return {reviewtype.name} + })} @@ -139,7 +169,7 @@ const OIPCItem = (props) => { select variant="outlined" fullWidth - value={oipc.reason} + // value={getNameFromId("REASON", oipc.reasonid)} label="Reason" onChange = {(event) => handleReason(event.target.value)} required={true} @@ -155,16 +185,14 @@ const OIPCItem = (props) => { select variant="outlined" fullWidth - value={oipc.status} + value={getNameFromId("STATUS", oipc.statusid)} label="Status" onChange = {(event) => handleStatus(event.target.value)} required={true} > - Mediation - Investigation - Inquiry - Awaiting Order - Closed + {oipcStatuses.map((status) => { + return {status.name} + })} @@ -185,28 +213,40 @@ const OIPCItem = (props) => { variant="outlined" onChange = {(event) => handleOutcome(event.target.value)} fullWidth - value={oipc.outcome} + value={getNameFromId("OUTCOME", oipc.outcomeid)} label="Outcome" required={true} > - Abandoned - Withdrawn - Resolved in Mediation - Closed + {oipcOutcomes.map((outcome) => { + return {outcome.name} + })} + + handleClosedDate(event.target.value)} + InputLabelProps={{ shrink: true }} + InputProps={{inputProps: { max: oipc.closeddate || formatDate(new Date())} }} + type="date" + /> +

In Inquiry?

handleInquiry(true)} />} label="Yes" /> handleInquiry(false)} />} label="No" @@ -215,13 +255,13 @@ const OIPCItem = (props) => {

In Judicial Review?

handleJudicalReview(true)} />} label="Yes" /> handleJudicalReview(false)} />} label="No" @@ -230,13 +270,13 @@ const OIPCItem = (props) => {

In Subsequent Appeal?

handleSubsequentAppeal(true)} />} label="Yes" /> handleSubsequentAppeal(false)} />} label="No" diff --git a/forms-flow-web/src/modules/FOI/foiRequestsReducer.js b/forms-flow-web/src/modules/FOI/foiRequestsReducer.js index 8dd27296b..0c090a82e 100644 --- a/forms-flow-web/src/modules/FOI/foiRequestsReducer.js +++ b/forms-flow-web/src/modules/FOI/foiRequestsReducer.js @@ -145,6 +145,9 @@ const initialState = { ".jpg", ], conversionFormats: [], + oipcOutcomes: [], + oipcStatuses: [], + oipcReviewtypes: [], }; const foiRequests = (state = initialState, action) => { @@ -307,6 +310,12 @@ const foiRequests = (state = initialState, action) => { return { ...state, recordFormats: action.payload }; case FOI_ACTION_CONSTANTS.CONVERSION_FORMATS: return { ...state, conversionFormats: action.payload }; + case FOI_ACTION_CONSTANTS.OIPC_OUTCOMES: + return { ...state, oipcOutcomes: action.payload }; + case FOI_ACTION_CONSTANTS.OIPC_STATUSES: + return { ...state, oipcStatuses: action.payload }; + case FOI_ACTION_CONSTANTS.OIPC_REVIEWTYPES: + return { ...state, oipcReviewtypes: action.payload }; default: return state; } diff --git a/request-management-api/request_api/services/foirequest/requestservicegetter.py b/request-management-api/request_api/services/foirequest/requestservicegetter.py index d3fedf68b..11ec9c2d8 100644 --- a/request-management-api/request_api/services/foirequest/requestservicegetter.py +++ b/request-management-api/request_api/services/foirequest/requestservicegetter.py @@ -218,6 +218,7 @@ def getoipcdetails(self, ministryrequestid, ministryrequestversion): for entry in _oipclist: oipc = { "oipcid": entry["oipcid"], + "oipcno": entry["oipcno"], "reviewtypeid": entry["reviewtypeid"], "reasonid": entry["reasonid"], "statusid": entry["statusid"], From 54f582a1c89fddb3996b26fa3aaf7f461f762569 Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Wed, 22 Nov 2023 12:04:59 -0800 Subject: [PATCH 024/238] Add OIPCReviewTypesReasons table and update endpoint --- .../3b399ca506fe_create_oipc_tables.py | 30 +++++++++++++ .../models/OIPCReviewTypesReasons.py | 43 +++++++++++++++++++ .../resources/foiflowmasterdata.py | 29 ++----------- .../request_api/services/oipcservice.py | 4 ++ 4 files changed, 81 insertions(+), 25 deletions(-) create mode 100644 request-management-api/request_api/models/OIPCReviewTypesReasons.py diff --git a/request-management-api/migrations/versions/3b399ca506fe_create_oipc_tables.py b/request-management-api/migrations/versions/3b399ca506fe_create_oipc_tables.py index e426ec587..386eb9c68 100644 --- a/request-management-api/migrations/versions/3b399ca506fe_create_oipc_tables.py +++ b/request-management-api/migrations/versions/3b399ca506fe_create_oipc_tables.py @@ -10,6 +10,7 @@ from sqlalchemy.dialects import postgresql from sqlalchemy import Table, Column, Integer, String, MetaData meta = MetaData() +from sqlalchemy.sql.schema import ForeignKey # revision identifiers, used by Alembic. @@ -34,6 +35,14 @@ def upgrade(): sa.PrimaryKeyConstraint('reasonid') ) + reviewtypes_reasons_table = op.create_table('OIPCReviewTypesReasons', + sa.Column('reviewtypereasonid', sa.Integer(), autoincrement=True, nullable=False), + sa.Column('reviewtypeid', sa.Integer(), ForeignKey('OIPCReviewTypes.reviewtypeid'), unique=False, nullable=False), + sa.Column('reasonid', sa.Integer(), ForeignKey('OIPCReasons.reasonid'), unique=False, nullable=False), + sa.Column('isactive', sa.Boolean(), unique=False, nullable=False), + sa.PrimaryKeyConstraint('reviewtypereasonid'), + ) + statusestable = op.create_table('OIPCStatuses', sa.Column('statusid', sa.Integer(), autoincrement=True, nullable=False), sa.Column('name', sa.String(length=100), unique=False, nullable=False), @@ -102,7 +111,28 @@ def upgrade(): ('Decision Partially Upheld', True), ('Decision Overturned', True);commit;''') + op.execute('''INSERT INTO public."OIPCReviewTypesReasons" (reviewtypeid, reasonid, isactive) + VALUES + (1, 1, True), + (1, 4, True), + (1, 5, True), + (1, 6, True), + (1, 8, True), + (1, 16, True), + (2, 2, True), + (2, 3, True), + (2, 9, True), + (2, 10, True), + (2, 11, True), + (2, 12, True), + (2, 13, True), + (2, 14, True), + (2, 15, True), + (2, 16, True), + (3, 16, True);commit;''') + def downgrade(): + op.drop_table('OIPCReviewTypesReasons') op.drop_table('OIPCReviewTypes') op.drop_table('OIPCReasons') op.drop_table('OIPCStatuses') diff --git a/request-management-api/request_api/models/OIPCReviewTypesReasons.py b/request-management-api/request_api/models/OIPCReviewTypesReasons.py new file mode 100644 index 000000000..3fc17e221 --- /dev/null +++ b/request-management-api/request_api/models/OIPCReviewTypesReasons.py @@ -0,0 +1,43 @@ +from .db import db, ma +from sqlalchemy.orm import relationship, backref +from sqlalchemy.sql.schema import ForeignKey +from sqlalchemy import text + +class OIPCReviewTypesReasons(db.Model): + __tablename__ = 'OIPCReviewTypesReasons' + # Defining the columns + reviewtypereasonid = db.Column(db.Integer, primary_key=True,autoincrement=True) + reviewtypeid = db.Column(db.Integer, ForeignKey('FOIReviewTypes')) + relationship("FOIReviewTypes", backref=backref("FOIReviewTypes"), uselist=False) + reasonid = db.Column(db.Integer, ForeignKey('FOIReasons')) + relationship("FOIReasons", backref=backref("FOIReasons"), uselist=False) + isactive = db.Column(db.Boolean, unique=False, nullable=False) + + @classmethod + def getreviewtypeswithreasons(cls): + type_schema = ReviewTypeReasonSchema(many=True) + sql = ''' + SELECT types.reviewtypeid, reasons.reasonid, reasons.name as reason_name, types.name as type_name, typereason.isactive as reviewtypereason_isactive, reasons.isactive as reason_isactive, types.isactive as reviewtype_isactive FROM public."OIPCReviewTypesReasons" typereason + JOIN public."OIPCReasons" reasons + ON reasons.reasonid = typereason.reasonid + JOIN public."OIPCReviewTypes" types + ON types.reviewtypeid = typereason.reviewtypeid + ORDER BY reviewtypereasonid ASC + ''' + rs = db.session.execute(text(sql)) + reviewtypereasons = [] + for row in rs: + reviewtypereasons.append({ + "reviewtypeid": row["reviewtypeid"], + "reasonid": row["reasonid"], + "reason_name": row["reason_name"], + "type_name": row["type_name"], + "reviewtypereason_isactive": row["reviewtypereason_isactive"], + "reviewtype_isactive": row["reviewtype_isactive"], + "reason_isactive": row["reason_isactive"], + }) + return reviewtypereasons + +class ReviewTypeReasonSchema(ma.Schema): + class Meta: + fields = ('reviewtypereasonid', 'reviewtypeid', 'reasonid', 'isactive') \ No newline at end of file diff --git a/request-management-api/request_api/resources/foiflowmasterdata.py b/request-management-api/request_api/resources/foiflowmasterdata.py index 2d75d602c..297880fbf 100644 --- a/request-management-api/request_api/resources/foiflowmasterdata.py +++ b/request-management-api/request_api/resources/foiflowmasterdata.py @@ -385,24 +385,24 @@ def post(): @cors_preflight('GET,OPTIONS') @API.route('/foiflow/oipc/reviewtypes') class FOIFlowOIPCReviewTypes(Resource): - """Retrieves OIPC review types + """Retrieves OIPC review types along with reasons for each type """ @staticmethod @TRACER.trace() @cross_origin(origins=allowedorigins()) # @auth.require @request_api.cache.cached( - key_prefix="oipcreviewtypes", + key_prefix="oipcreviewtypesreasons", unless=cache_filter, response_filter=response_filter ) def get(): try: - data = oipcservice().getreviewtypes() + data = oipcservice().getreviewtypeswithreasons() jsondata = json.dumps(data) return jsondata , 200 except BusinessException: - return "Error happened while accessing OIPC review types" , 500 + return "Error happened while accessing OIPC review types and associated reasons" , 500 @cors_preflight('GET,OPTIONS') @API.route('/foiflow/oipc/statuses') @@ -426,27 +426,6 @@ def get(): except BusinessException: return "Error happened while accessing OIPC statuses" , 500 -@cors_preflight('GET,OPTIONS') -@API.route('/foiflow/oipc/reasons') -class FOIFlowOIPCReasons(Resource): - """Retrieves OIPC reasons - """ - @staticmethod - @TRACER.trace() - @cross_origin(origins=allowedorigins()) - # @auth.require - @request_api.cache.cached( - key_prefix="oipcreasons", - unless=cache_filter, - response_filter=response_filter - ) - def get(): - try: - data = oipcservice().getreasons() - jsondata = json.dumps(data) - return jsondata , 200 - except BusinessException: - return "Error happened while accessing OIPC reasons" , 500 @cors_preflight('GET,OPTIONS') @API.route('/foiflow/oipc/outcomes') diff --git a/request-management-api/request_api/services/oipcservice.py b/request-management-api/request_api/services/oipcservice.py index 2ea4719f8..636044430 100644 --- a/request-management-api/request_api/services/oipcservice.py +++ b/request-management-api/request_api/services/oipcservice.py @@ -3,6 +3,7 @@ from request_api.models.OIPCReasons import OIPCReasons from request_api.models.OIPCOutcomes import OIPCOutcomes from request_api.models.OIPCInquiryOutcomes import OIPCInquiryOutcomes +from request_api.models.OIPCReviewTypesReasons import OIPCReviewTypesReasons class oipcservice: """ OIPC service @@ -10,6 +11,9 @@ class oipcservice: def getreviewtypes(self): return OIPCReviewTypes.getreviewtypes() + def getreviewtypeswithreasons(self): + return OIPCReviewTypesReasons.getreviewtypeswithreasons() + def getreasons(self): return OIPCReasons.getreasons() From 9f8964433eb1e29b51f2c0bd27f016777d86562d Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Wed, 22 Nov 2023 13:54:55 -0800 Subject: [PATCH 025/238] BE integration -> fetch calles for master, transacntional oipc data completed. intergration of data to FE + validation + save WIP --- .../FOI/FOIRequest/OIPCDetails/Index.jsx | 6 +- .../OIPCDetails/OIPCDetailsList.jsx | 1 - .../FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 55 +++++++++---------- 3 files changed, 32 insertions(+), 30 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx index d9fa50c4b..fac3bb4ae 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx @@ -52,7 +52,11 @@ const OIPCDetails = (props) => { investigator: "", outcomeid: null, isjudicialreview: false, - issubsequentappeal: false + issubsequentappeal: false, + reviewtype: "", + status: "", + outcome: "", + reason: "", }]; }) } diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx index 16e5cdfe6..b47afe895 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx @@ -6,7 +6,6 @@ import { faTrash } from '@fortawesome/free-solid-svg-icons'; const OIPCDetailsList = (props) => { const {oipcData, removeOIPC, updateOIPC} = props; - const OIPCItems = oipcData?.map((oipcObj, index) => { return ( <> diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index 02ed42071..8c72986c9 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -1,11 +1,15 @@ import { TextField, FormControlLabel, MenuItem, Grid, Checkbox } from '@material-ui/core'; -import { useState } from "react"; -import { useSelector } from "react-redux"; +import { useState, useEffect } from "react"; import { formatDate } from "../../../../helper/FOI/helper"; - +import { useSelector } from "react-redux"; const OIPCItem = (props) => { const {oipcObj, updateOIPC} = props; + + //App State + const oipcOutcomes = useSelector(state=> state.foiRequests.oipcOutcomes); + const oipcStatuses = useSelector(state=> state.foiRequests.oipcStatuses); + const oipcReviewtypes = useSelector(state=> state.foiRequests.oipcReviewtypes); //Local State const [oipc, setOipc] = useState({ @@ -21,18 +25,13 @@ const OIPCItem = (props) => { investigator: oipcObj?.investigator, outcomeid: oipcObj?.outcomeid, isjudicialreview: oipcObj?.isjudicialreview, - issubsequentappeal: oipcObj?.issubsequentappeal, + reviewtypeName: oipcObj?.reviewtypeName, + reasonName: "", + statusName: oipcObj?.statusName, + outcomeName: oipcObj?.outcomeName, }); - //App State - const oipcOutcomes = useSelector(state=> state.foiRequests.oipcOutcomes); - const oipcStatuses = useSelector(state=> state.foiRequests.oipcStatuses); - const oipcReviewtypes = useSelector(state=> state.foiRequests.oipcReviewtypes); - console.log(oipc); - console.log(oipcOutcomes) - console.log(oipcStatuses) - console.log(oipcReviewtypes) //Functions const handleReviewType = (value) => { @@ -91,20 +90,16 @@ const OIPCItem = (props) => { newOIPCObj.issubsequentappeal = value; updateOIPC(newOIPCObj); } - const getNameFromId = (attribute, id) => { - if (attribute === "STATUS") { - const status = oipcStatuses.find(status => status.statusid === id); - return status.name; - } - if (attribute === "REVIEW_TYPE") { - const reviewtype = oipcReviewtypes.find(reviewtype => reviewtype.reviewtypeid === id); - return reviewtype.name; - } - if (attribute === "OUTCOME") { - const outcome = oipcOutcomes.find(outcome => outcome.outcomeid === id); - return outcome.name; - } + const generateNamesFromOIPCId = (oipcObj) => { + const reviewtype = oipcReviewtypes.find(reviewtype => reviewtype.reviewtypeid === oipcObj.reviewtypeid); + const status = oipcStatuses.find(status => status.statusid === oipcObj.statusid); + const outcome = oipcOutcomes.find(outcome => outcome.outcomeid === oipcObj.outcomeid); + + oipcObj.reviewtypeName = reviewtype ? reviewtype.name : ""; + oipcObj.statusName = status ? status.name : ""; + oipcObj.outcomeName = outcome ? outcome.name : ""; } + //REFACTOR THIS!!! const filterReasonOptions = (reviewType) => { if (reviewType === "Complaint") { @@ -120,6 +115,10 @@ const OIPCItem = (props) => { } const reasons = filterReasonOptions(oipc.reviewType) + useEffect(() => { + generateNamesFromOIPCId(oipcObj); + }, [oipcObj]) + return ( <> @@ -153,7 +152,7 @@ const OIPCItem = (props) => { select variant="outlined" fullWidth - value={getNameFromId("REVIEW_TYPE", oipc.reviewtypeid)} + value={oipc.reviewtypeid} label="Review Type" onChange={(event) => handleReviewType(event.target.value)} required={true} @@ -185,7 +184,7 @@ const OIPCItem = (props) => { select variant="outlined" fullWidth - value={getNameFromId("STATUS", oipc.statusid)} + value={oipc.statusid} label="Status" onChange = {(event) => handleStatus(event.target.value)} required={true} @@ -213,7 +212,7 @@ const OIPCItem = (props) => { variant="outlined" onChange = {(event) => handleOutcome(event.target.value)} fullWidth - value={getNameFromId("OUTCOME", oipc.outcomeid)} + value={oipc.outcomeid} label="Outcome" required={true} > From 88d45e14b519e2744bee2a5ad1d4e17f5e36683d Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Wed, 22 Nov 2023 16:34:16 -0800 Subject: [PATCH 026/238] BE integration completed. WIP Validation + BE Save --- .../components/FOI/FOIRequest/FOIRequest.js | 2 +- .../FOI/FOIRequest/OIPCDetails/Index.jsx | 6 +-- .../FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 42 ++++++++----------- 3 files changed, 21 insertions(+), 29 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index 2142892cf..6ec696b18 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -1216,7 +1216,7 @@ const FOIRequest = React.memo(({ userDetail }) => { divisions={requestDetails.divisions} /> )} - {showOIPCDetails && ( + {showOIPCDetails && requestDetails.oipcdetails && ( diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx index fac3bb4ae..e44f4c500 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx @@ -19,6 +19,8 @@ const OIPCDetails = (props) => { item.id = index; return item; }); + } else { + return oipcData; } } const [oipcData, setOipcData] = useState(createOIPCId(oipcDetails)); @@ -53,10 +55,6 @@ const OIPCDetails = (props) => { outcomeid: null, isjudicialreview: false, issubsequentappeal: false, - reviewtype: "", - status: "", - outcome: "", - reason: "", }]; }) } diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index 8c72986c9..be04ac841 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -26,7 +26,7 @@ const OIPCItem = (props) => { outcomeid: oipcObj?.outcomeid, isjudicialreview: oipcObj?.isjudicialreview, reviewtypeName: oipcObj?.reviewtypeName, - reasonName: "", + reasonName: oipcObj?.reasonName, statusName: oipcObj?.statusName, outcomeName: oipcObj?.outcomeName, }); @@ -37,7 +37,7 @@ const OIPCItem = (props) => { const handleReviewType = (value) => { const newOIPCObj = oipc; newOIPCObj.reviewtypeid = value; - newOIPCObj.reasonid = -1; + newOIPCObj.reasonid = null; updateOIPC(newOIPCObj); } const handleOIPCNumber = (value) => { @@ -91,30 +91,21 @@ const OIPCItem = (props) => { updateOIPC(newOIPCObj); } const generateNamesFromOIPCId = (oipcObj) => { - const reviewtype = oipcReviewtypes.find(reviewtype => reviewtype.reviewtypeid === oipcObj.reviewtypeid); + const reviewtype = oipcReviewtypes.find(reviewtype => reviewtype.reviewtypeid === oipcObj.reviewtypeid && reviewtype.reasonid === oipcObj.reasonid); const status = oipcStatuses.find(status => status.statusid === oipcObj.statusid); const outcome = oipcOutcomes.find(outcome => outcome.outcomeid === oipcObj.outcomeid); - oipcObj.reviewtypeName = reviewtype ? reviewtype.name : ""; + oipcObj.reviewtypeName = reviewtype ? reviewtype.type_name : ""; oipcObj.statusName = status ? status.name : ""; oipcObj.outcomeName = outcome ? outcome.name : ""; + oipcObj.reasonName = reviewtype ? reviewtype.reason_name : ""; } - - //REFACTOR THIS!!! - const filterReasonOptions = (reviewType) => { - if (reviewType === "Complaint") { - return ["Adequate search","Extension", "Fee Amount", "Fee Waiver", "Duty to Assist", "Other"]; - } - if (reviewType === "Review") { - return ["Application of Exceptions", "Deemed Refusal", "TPN - 22", "TPN - 21", "TPN - 18.1", "Reg 3", "Reg 4", "Reg 5", "s. 43", "Other"]; - } - if (reviewType === "Investigation") { - return ["Other"] - } - return ["Adequate search","Extension", "Fee Amount", "Fee Waiver", "Duty to Assist", "Application of Exceptions", "Deemed Refusal", "TPN - 22", "TPN - 21", "TPN - 18.1", "Reg 3", "Reg 4", "Reg 5", "s. 43", "Other"]; + const uniqueReviewTypes = (oipcReviewTypes) => { + const uniqeValues = {}; + return oipcReviewTypes.filter(reviewtype => !uniqeValues[reviewtype.type_name] && (uniqeValues[reviewtype.type_name] = true)); } - const reasons = filterReasonOptions(oipc.reviewType) + //useEffect to create name attributes using id's for oipcObject useEffect(() => { generateNamesFromOIPCId(oipcObj); }, [oipcObj]) @@ -157,8 +148,8 @@ const OIPCItem = (props) => { onChange={(event) => handleReviewType(event.target.value)} required={true} > - {oipcReviewtypes.map((reviewtype) => { - return {reviewtype.name} + {uniqueReviewTypes(oipcReviewtypes).map((reviewtype) => { + return {reviewtype.type_name} })} @@ -168,14 +159,17 @@ const OIPCItem = (props) => { select variant="outlined" fullWidth - // value={getNameFromId("REASON", oipc.reasonid)} + value={oipc.reasonid} label="Reason" onChange = {(event) => handleReason(event.target.value)} required={true} > - {reasons.map((reason) => { - return {reason} - })} + {oipc.reviewtypeid ? + oipcReviewtypes.map((reviewtype) => { + if (reviewtype.reviewtypeid === oipc.reviewtypeid) { + return {reviewtype.reason_name} + } + }) : null} From a593a5e6b9ac64062a0340668d47a13c0e2976fb Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Thu, 23 Nov 2023 09:50:50 -0800 Subject: [PATCH 027/238] Update sql to insert with SELECT --- .../3b399ca506fe_create_oipc_tables.py | 104 +++++++++++++++--- 1 file changed, 86 insertions(+), 18 deletions(-) diff --git a/request-management-api/migrations/versions/3b399ca506fe_create_oipc_tables.py b/request-management-api/migrations/versions/3b399ca506fe_create_oipc_tables.py index 386eb9c68..8733a7034 100644 --- a/request-management-api/migrations/versions/3b399ca506fe_create_oipc_tables.py +++ b/request-management-api/migrations/versions/3b399ca506fe_create_oipc_tables.py @@ -112,24 +112,92 @@ def upgrade(): ('Decision Overturned', True);commit;''') op.execute('''INSERT INTO public."OIPCReviewTypesReasons" (reviewtypeid, reasonid, isactive) - VALUES - (1, 1, True), - (1, 4, True), - (1, 5, True), - (1, 6, True), - (1, 8, True), - (1, 16, True), - (2, 2, True), - (2, 3, True), - (2, 9, True), - (2, 10, True), - (2, 11, True), - (2, 12, True), - (2, 13, True), - (2, 14, True), - (2, 15, True), - (2, 16, True), - (3, 16, True);commit;''') + VALUES + ( + (SELECT reviewtypeid FROM public."OIPCReviewTypes" WHERE name = 'Complaint'), + (SELECT reasonid FROM public."OIPCReasons" WHERE name = 'Adequate Search'), + True + ), + ( + (SELECT reviewtypeid FROM public."OIPCReviewTypes" WHERE name = 'Complaint'), + (SELECT reasonid FROM public."OIPCReasons" WHERE name = 'Extension'), + True + ), + ( + (SELECT reviewtypeid FROM public."OIPCReviewTypes" WHERE name = 'Complaint'), + (SELECT reasonid FROM public."OIPCReasons" WHERE name = 'Fee Amount'), + True + ), + ( + (SELECT reviewtypeid FROM public."OIPCReviewTypes" WHERE name = 'Complaint'), + (SELECT reasonid FROM public."OIPCReasons" WHERE name = 'Fee Waiver'), + True + ), + ( + (SELECT reviewtypeid FROM public."OIPCReviewTypes" WHERE name = 'Complaint'), + (SELECT reasonid FROM public."OIPCReasons" WHERE name = 'Duty to Assist'), + True + ), + ( + (SELECT reviewtypeid FROM public."OIPCReviewTypes" WHERE name = 'Complaint'), + (SELECT reasonid FROM public."OIPCReasons" WHERE name = 'Other'), + True + ), + ( + (SELECT reviewtypeid FROM public."OIPCReviewTypes" WHERE name = 'Review'), + (SELECT reasonid FROM public."OIPCReasons" WHERE name = 'Application of Exceptions'), + True + ), + ( + (SELECT reviewtypeid FROM public."OIPCReviewTypes" WHERE name = 'Review'), + (SELECT reasonid FROM public."OIPCReasons" WHERE name = 'Deemed Refusal'), + True + ), + ( + (SELECT reviewtypeid FROM public."OIPCReviewTypes" WHERE name = 'Review'), + (SELECT reasonid FROM public."OIPCReasons" WHERE name = 'TPN - 22'), + True + ), + ( + (SELECT reviewtypeid FROM public."OIPCReviewTypes" WHERE name = 'Review'), + (SELECT reasonid FROM public."OIPCReasons" WHERE name = 'TPN - 21'), + True + ), + ( + (SELECT reviewtypeid FROM public."OIPCReviewTypes" WHERE name = 'Review'), + (SELECT reasonid FROM public."OIPCReasons" WHERE name = 'TPN - 18.1'), + True + ), + ( + (SELECT reviewtypeid FROM public."OIPCReviewTypes" WHERE name = 'Review'), + (SELECT reasonid FROM public."OIPCReasons" WHERE name = 'Reg 3'), + True + ), + ( + (SELECT reviewtypeid FROM public."OIPCReviewTypes" WHERE name = 'Review'), + (SELECT reasonid FROM public."OIPCReasons" WHERE name = 'Reg 4'), + True + ), + ( + (SELECT reviewtypeid FROM public."OIPCReviewTypes" WHERE name = 'Review'), + (SELECT reasonid FROM public."OIPCReasons" WHERE name = 'Reg 5'), + True + ), + ( + (SELECT reviewtypeid FROM public."OIPCReviewTypes" WHERE name = 'Review'), + (SELECT reasonid FROM public."OIPCReasons" WHERE name = 's. 43'), + True + ), + ( + (SELECT reviewtypeid FROM public."OIPCReviewTypes" WHERE name = 'Review'), + (SELECT reasonid FROM public."OIPCReasons" WHERE name = 'Other'), + True + ), + ( + (SELECT reviewtypeid FROM public."OIPCReviewTypes" WHERE name = 'Investigation'), + (SELECT reasonid FROM public."OIPCReasons" WHERE name = 'Other'), + True + );commit;''') def downgrade(): op.drop_table('OIPCReviewTypesReasons') From 025ce067979e34df5f59b3d88113ce667d232989 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Thu, 23 Nov 2023 11:18:30 -0800 Subject: [PATCH 028/238] Inquiry Story/feature completed. WIP Validation + Save of OIPCDetails to BE --- .../src/actions/FOI/foiActionConstants.js | 1 + .../src/actions/FOI/foiRequestActions.js | 7 ++ .../src/apiManager/endpoints/index.js | 1 + .../services/FOI/foiMasterDataServices.js | 23 ++++++ .../components/FOI/FOIRequest/FOIRequest.js | 2 + .../FOI/FOIRequest/OIPCDetails/Index.jsx | 28 +++++--- .../OIPCDetails/OIPCDetailsList.jsx | 1 + .../FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 70 ++++++++++++++++++- .../src/modules/FOI/foiRequestsReducer.js | 3 + 9 files changed, 123 insertions(+), 13 deletions(-) diff --git a/forms-flow-web/src/actions/FOI/foiActionConstants.js b/forms-flow-web/src/actions/FOI/foiActionConstants.js index ef0bc6dac..8a94f7f00 100644 --- a/forms-flow-web/src/actions/FOI/foiActionConstants.js +++ b/forms-flow-web/src/actions/FOI/foiActionConstants.js @@ -93,6 +93,7 @@ const FOI_ACTION_CONSTANTS = { OIPC_OUTCOMES: "OIPC_OUTCOMES", OIPC_STATUSES: "OIPC_STATUSES", OIPC_REVIEWTYPES: "OIPC_REVIEWTYPES", + OIPC_INQUIRYOUTCOMES: "OIPC_INQUIRYOUTCOMES", }; export default FOI_ACTION_CONSTANTS; diff --git a/forms-flow-web/src/actions/FOI/foiRequestActions.js b/forms-flow-web/src/actions/FOI/foiRequestActions.js index 46ffcf494..ad9a7beb7 100644 --- a/forms-flow-web/src/actions/FOI/foiRequestActions.js +++ b/forms-flow-web/src/actions/FOI/foiRequestActions.js @@ -446,3 +446,10 @@ export const setOIPCReviewtypes = (data) => (dispatch) => { payload: data, }); }; + +export const setOIPCInquiryoutcomes = (data) => (dispatch) => { + dispatch({ + type: FOI_ACTION_CONSTANTS.OIPC_INQUIRYOUTCOMES, + payload: data, + }); +}; \ No newline at end of file diff --git a/forms-flow-web/src/apiManager/endpoints/index.js b/forms-flow-web/src/apiManager/endpoints/index.js index 60762afca..9e2ddb7d7 100644 --- a/forms-flow-web/src/apiManager/endpoints/index.js +++ b/forms-flow-web/src/apiManager/endpoints/index.js @@ -137,5 +137,6 @@ const API = { FOI_GET_OIPC_OUTCOMES: `${FOI_BASE_API_URL}/api/foiflow/oipc/outcomes`, FOI_GET_OIPC_STATUSES: `${FOI_BASE_API_URL}/api/foiflow/oipc/statuses`, FOI_GET_OIPC_REVIEWTYPES: `${FOI_BASE_API_URL}/api/foiflow/oipc/reviewtypes`, + FOI_GET_OIPC_INQUIRYOUTCOMES: `${FOI_BASE_API_URL}/api/foiflow/oipc/inquiryoutcomes`, }; export default API; diff --git a/forms-flow-web/src/apiManager/services/FOI/foiMasterDataServices.js b/forms-flow-web/src/apiManager/services/FOI/foiMasterDataServices.js index 16bd8476b..5399f22da 100644 --- a/forms-flow-web/src/apiManager/services/FOI/foiMasterDataServices.js +++ b/forms-flow-web/src/apiManager/services/FOI/foiMasterDataServices.js @@ -25,6 +25,7 @@ import { setOIPCOutcomes, setOIPCStatuses, setOIPCReviewtypes, + setOIPCInquiryoutcomes, } from "../../../actions/FOI/foiRequestActions"; import { fnDone, catchError } from "./foiServicesUtil"; import UserService from "../../../services/UserService"; @@ -577,4 +578,26 @@ import { }); }; }; + + export const fetchOIPCInquiryoutcomes = () => { + return (dispatch) => { + httpGETRequest(API.FOI_GET_OIPC_INQUIRYOUTCOMES, {}, UserService.getToken()) + .then((res) => { + if (res.data) { + const oipcInquiryoutcomes = res.data; + dispatch(setOIPCInquiryoutcomes(oipcInquiryoutcomes)); + dispatch(setFOILoader(false)); + } else { + console.log("Error while fetching OIPC inqiuryoutcomes master data", res); + dispatch(serviceActionError(res)); + dispatch(setFOILoader(false)); + } + }) + .catch((error) => { + console.log("Error while fetching OIPC inqiuryoutcomes master data", error); + dispatch(serviceActionError(error)); + dispatch(setFOILoader(false)); + }); + }; + }; \ No newline at end of file diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index 6ec696b18..46a69644e 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -27,6 +27,7 @@ import { fetchOIPCOutcomes, fetchOIPCStatuses, fetchOIPCReviewtypes, + fetchOIPCInquiryoutcomes } from "../../../apiManager/services/FOI/foiMasterDataServices"; import { fetchFOIRequestDetailsWrapper, @@ -300,6 +301,7 @@ const FOIRequest = React.memo(({ userDetail }) => { dispatch(fetchOIPCOutcomes()); dispatch(fetchOIPCStatuses()); dispatch(fetchOIPCReviewtypes()); + dispatch(fetchOIPCInquiryoutcomes()); if (bcgovcode) dispatch(fetchFOIMinistryAssignedToList(bcgovcode)); }, [requestId, ministryId, comment, attachments]); diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx index e44f4c500..4edf4bcb0 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx @@ -13,17 +13,31 @@ const OIPCDetails = (props) => { const { oipcDetails } = props; //Local State - const createOIPCId = (oipcData) => { + const createOIPCIds = (oipcData) => { if (oipcData.length > 0) { return oipcData.map((item, index) => { item.id = index; return item; }); } else { - return oipcData; + return [{ + id: 0, + oipcno: "", + reviewtypeid: null, + reasonid: null, + statusid: null, + isinquiry: false, + inquiryattributes: null, + receiveddate: "", + closeddate: "", + investigator: "", + outcomeid: null, + isjudicialreview: false, + issubsequentappeal: false, + }]; } } - const [oipcData, setOipcData] = useState(createOIPCId(oipcDetails)); + const [oipcData, setOipcData] = useState(createOIPCIds(oipcDetails)); //Styling const useStyles = makeStyles({ @@ -97,10 +111,4 @@ const OIPCDetails = (props) => { ); } -export default OIPCDetails; - -//IDEA = MasterData is held in a oipcData [{}] state (there is a backend api call to generate the existing oipc data). This is mapped in OIPCDetailsList where each elm is mapped as a OIPCItem. Each OIPC Item has EDITABLE Fields (unless oipcObj outcome value exists? -> therefore we disable the field) -//EACH OIPCITEM HAS ITS OWN INTERNAL STATE WE CAN change and if changed -> the oipcData state wil change as well -// When add button is clicked, we add a new oipcObj to the oipcData state which then creates a new oipcITEM with its own default state which can be edited. -// if any oipcObjs in the oipcData state are missing any of the mandatory fields -> Save button cannot be selected./is disalbed -// When save button is enabled and clicked -> we send the backend api requeset and save the oipc data in backend by sending the master oipc data over. \ No newline at end of file +export default OIPCDetails; \ No newline at end of file diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx index b47afe895..dc5cb8b72 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx @@ -6,6 +6,7 @@ import { faTrash } from '@fortawesome/free-solid-svg-icons'; const OIPCDetailsList = (props) => { const {oipcData, removeOIPC, updateOIPC} = props; + const OIPCItems = oipcData?.map((oipcObj, index) => { return ( <> diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index be04ac841..b5a8bea92 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -10,6 +10,7 @@ const OIPCItem = (props) => { const oipcOutcomes = useSelector(state=> state.foiRequests.oipcOutcomes); const oipcStatuses = useSelector(state=> state.foiRequests.oipcStatuses); const oipcReviewtypes = useSelector(state=> state.foiRequests.oipcReviewtypes); + const oipcInquiryoutcomes = useSelector(state=> state.foiRequests.oipcInquiryoutcomes); //Local State const [oipc, setOipc] = useState({ @@ -77,6 +78,15 @@ const OIPCItem = (props) => { } const handleInquiry = (value) => { const newOIPCObj = oipc; + if (value === false) { + newOIPCObj.inquiryattributes = null; + } else { + newOIPCObj.inquiryattributes = { + inquirydate: "", + orderno: "", + inquiryoutcomeid: null, + }; + } newOIPCObj.isinquiry = value; updateOIPC(newOIPCObj); } @@ -90,6 +100,19 @@ const OIPCItem = (props) => { newOIPCObj.issubsequentappeal = value; updateOIPC(newOIPCObj); } + const handleInquiryFields = (value, attribute) => { + const newOIPCObj = oipc; + if (attribute === "COMPLYDATE") { + newOIPCObj.inquiryattributes.inquirydate = value; + } + if (attribute === "ORDERNO") { + newOIPCObj.inquiryattributes.orderno = value; + } + if (attribute === "INQUIRYOUTCOME") { + newOIPCObj.inquiryattributes.inquiryoutcomeid = value; + } + updateOIPC(newOIPCObj); + } const generateNamesFromOIPCId = (oipcObj) => { const reviewtype = oipcReviewtypes.find(reviewtype => reviewtype.reviewtypeid === oipcObj.reviewtypeid && reviewtype.reasonid === oipcObj.reasonid); const status = oipcStatuses.find(status => status.statusid === oipcObj.statusid); @@ -193,7 +216,6 @@ const OIPCItem = (props) => { fullWidth label="Investigator/Adjudicator" variant="outlined" - required={true} onChange = {(event) => handleInvestiagtor(event.target.value)} value={oipc.investigator} InputLabelProps={{ shrink: true }} @@ -208,7 +230,6 @@ const OIPCItem = (props) => { fullWidth value={oipc.outcomeid} label="Outcome" - required={true} > {oipcOutcomes.map((outcome) => { return {outcome.name} @@ -220,7 +241,6 @@ const OIPCItem = (props) => { fullWidth label="Closed Date" variant="outlined" - required={true} value={oipc.closeddate} onChange = {(event) => handleClosedDate(event.target.value)} InputLabelProps={{ shrink: true }} @@ -276,6 +296,50 @@ const OIPCItem = (props) => { />
+ {oipc.isinquiry && + + + handleInquiryFields(event.target.value, "COMPLYDATE")} + InputLabelProps={{ shrink: true }} + InputProps={{inputProps: { min: oipc.receiveddate } }} + type="date" + /> + + + handleInquiryFields(event.target.value, "ORDERNO")} + InputLabelProps={{ shrink: true }} + /> + + + handleInquiryFields(event.target.value, "INQUIRYOUTCOME")} + fullWidth + value={oipc.inquiryattributes.inquiryoutcomeid} + label="Outcome" + > + {oipcInquiryoutcomes.map((inquiryoutcome) => { + return {inquiryoutcome.name} + })} + + + + } ); } diff --git a/forms-flow-web/src/modules/FOI/foiRequestsReducer.js b/forms-flow-web/src/modules/FOI/foiRequestsReducer.js index 0c090a82e..9edb8ab4e 100644 --- a/forms-flow-web/src/modules/FOI/foiRequestsReducer.js +++ b/forms-flow-web/src/modules/FOI/foiRequestsReducer.js @@ -148,6 +148,7 @@ const initialState = { oipcOutcomes: [], oipcStatuses: [], oipcReviewtypes: [], + oipcInquiryoutcomes: [], }; const foiRequests = (state = initialState, action) => { @@ -316,6 +317,8 @@ const foiRequests = (state = initialState, action) => { return { ...state, oipcStatuses: action.payload }; case FOI_ACTION_CONSTANTS.OIPC_REVIEWTYPES: return { ...state, oipcReviewtypes: action.payload }; + case FOI_ACTION_CONSTANTS.OIPC_INQUIRYOUTCOMES: + return { ...state, oipcInquiryoutcomes: action.payload }; default: return state; } From a8d46253cfd582982a37c40a18a151a4bd3b92d8 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Thu, 23 Nov 2023 15:09:42 -0800 Subject: [PATCH 029/238] Validation work completed. WIP BE post/save + refactor + styling final --- .../components/FOI/FOIRequest/FOIRequest.js | 12 +- .../OIPCDetails/AdditionalInquiryFields.jsx | 0 .../FOI/FOIRequest/OIPCDetails/Index.jsx | 130 +++++------------- .../FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 8 ++ .../FOI/FOIRequest/OIPCDetails/oipcHook.js | 80 +++++++++++ .../src/components/FOI/FOIRequest/utils.js | 10 +- 6 files changed, 135 insertions(+), 105 deletions(-) delete mode 100644 forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/AdditionalInquiryFields.jsx create mode 100644 forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index 46a69644e..7132275fe 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -94,6 +94,7 @@ import { DISABLE_GATHERINGRECORDS_TAB } from "../../../constants/constants"; import _ from "lodash"; import { MinistryNeedsScanning } from "../../../constants/FOI/enum"; import OIPCDetails from "./OIPCDetails/Index"; +import useOIPCHook from "./OIPCDetails/oipcHook"; const useStyles = makeStyles((theme) => ({ root: { @@ -256,8 +257,9 @@ const FOIRequest = React.memo(({ userDetail }) => { const [isIAORestricted, setIsIAORestricted] = useState(false); const [redactedSections, setRedactedSections] = useState(""); const [isMCFPersonal, setIsMCFPersonal] = useState(bcgovcode.replaceAll('"', '') == "MCF" && requestDetails.requestType == FOI_COMPONENT_CONSTANTS.REQUEST_TYPE_PERSONAL); + const {oipcData, addOIPC, removeOIPC, updateOIPC} = useOIPCHook(); const [showOIPCDetails, setShowOIPCDetails] = useState(true); - + useEffect(() => { if (window.location.href.indexOf("comments") > -1) { tabclick("Comments"); @@ -661,7 +663,8 @@ const FOIRequest = React.memo(({ userDetail }) => { requiredRequestDetailsValues, requiredAxisDetails, isAddRequest, - _currentrequestStatus + _currentrequestStatus, + oipcData, ); const classes = useStyles(); @@ -1220,7 +1223,10 @@ const FOIRequest = React.memo(({ userDetail }) => { )} {showOIPCDetails && requestDetails.oipcdetails && ( )} diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/AdditionalInquiryFields.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/AdditionalInquiryFields.jsx deleted file mode 100644 index e69de29bb..000000000 diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx index 4edf4bcb0..c7a6985b1 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx @@ -1,4 +1,3 @@ -import { useState } from 'react'; import OIPCDetailsList from "./OIPCDetailsList"; import Accordion from '@material-ui/core/Accordion'; import AccordionSummary from '@material-ui/core/AccordionSummary'; @@ -10,105 +9,38 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faCirclePlus } from '@fortawesome/free-solid-svg-icons'; const OIPCDetails = (props) => { - const { oipcDetails } = props; - - //Local State - const createOIPCIds = (oipcData) => { - if (oipcData.length > 0) { - return oipcData.map((item, index) => { - item.id = index; - return item; - }); - } else { - return [{ - id: 0, - oipcno: "", - reviewtypeid: null, - reasonid: null, - statusid: null, - isinquiry: false, - inquiryattributes: null, - receiveddate: "", - closeddate: "", - investigator: "", - outcomeid: null, - isjudicialreview: false, - issubsequentappeal: false, - }]; - } + const { oipcData, addOIPC, removeOIPC, updateOIPC } = props; + //Styling + const useStyles = makeStyles({ + heading: { + color: '#FFF', + fontSize: '16px !important', + fontWeight: 'bold !important' + }, + accordionSummary: { + flexDirection: 'row-reverse' } - const [oipcData, setOipcData] = useState(createOIPCIds(oipcDetails)); - - //Styling - const useStyles = makeStyles({ - heading: { - color: '#FFF', - fontSize: '16px !important', - fontWeight: 'bold !important' - }, - accordionSummary: { - flexDirection: 'row-reverse' - } - }); - const classes = useStyles(); - - //Functions - const addOIPC = () => { - setOipcData((prev) => { - return [...prev, { - id: oipcData.length > 0 ? oipcData[oipcData.length - 1].id + 1 : 0, - oipcno: "", - reviewtypeid: null, - reasonid: null, - statusid: null, - isinquiry: false, - inquiryattributes: null, - receiveddate: "", - closeddate: "", - investigator: "", - outcomeid: null, - isjudicialreview: false, - issubsequentappeal: false, - }]; - }) - } - const removeOIPC = (oipcId) => { - setOipcData((prev) => { - const previousOIPCData = [...prev]; - return previousOIPCData.filter(oipc => oipcId !== oipc.id); - }); - } - const updateOIPC = (newOIPCObj) => { - setOipcData((prev) => { - const previousOIPCData = [...prev]; - return previousOIPCData.map((oipc) => { - if (oipc.id === newOIPCObj.id) { - return newOIPCObj; - } else { - return oipc; - } - }); - }); - } - - return ( -
- - }> - OIPC DETAILS - - - -
- -

Add Additional OIPC Complaint

-
-
-
-
- ); + }); + const classes = useStyles(); + + return ( +
+ + }> + OIPC DETAILS + + + +
+ +

Add Additional OIPC Complaint

+
+
+
+
+ ); } export default OIPCDetails; \ No newline at end of file diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index b5a8bea92..c1121bf93 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -145,6 +145,7 @@ const OIPCItem = (props) => { value={oipc.oipcno} onChange = {(event) => handleOIPCNumber(event.target.value)} InputLabelProps={{ shrink: true }} + error={oipc.oipcno === ""} /> @@ -158,6 +159,7 @@ const OIPCItem = (props) => { InputLabelProps={{ shrink: true }} InputProps={{inputProps: { max: oipc.receiveddate || formatDate(new Date())} }} type="date" + error={oipc.receiveddate === ""} /> @@ -170,6 +172,7 @@ const OIPCItem = (props) => { label="Review Type" onChange={(event) => handleReviewType(event.target.value)} required={true} + error={oipc.reviewtypeid === null} > {uniqueReviewTypes(oipcReviewtypes).map((reviewtype) => { return {reviewtype.type_name} @@ -186,6 +189,7 @@ const OIPCItem = (props) => { label="Reason" onChange = {(event) => handleReason(event.target.value)} required={true} + error={oipc.reasonid === null} > {oipc.reviewtypeid ? oipcReviewtypes.map((reviewtype) => { @@ -205,6 +209,7 @@ const OIPCItem = (props) => { label="Status" onChange = {(event) => handleStatus(event.target.value)} required={true} + error={oipc.statusid === null} > {oipcStatuses.map((status) => { return {status.name} @@ -309,6 +314,7 @@ const OIPCItem = (props) => { InputLabelProps={{ shrink: true }} InputProps={{inputProps: { min: oipc.receiveddate } }} type="date" + error={oipc.inquiryattributes.inquirydate === ""} /> @@ -320,6 +326,7 @@ const OIPCItem = (props) => { value={oipc.inquiryattributes.orderno} onChange = {(event) => handleInquiryFields(event.target.value, "ORDERNO")} InputLabelProps={{ shrink: true }} + error={oipc.inquiryattributes.orderno === ""} /> @@ -332,6 +339,7 @@ const OIPCItem = (props) => { fullWidth value={oipc.inquiryattributes.inquiryoutcomeid} label="Outcome" + error={oipc.inquiryattributes.inquiryoutcomeid === null} > {oipcInquiryoutcomes.map((inquiryoutcome) => { return {inquiryoutcome.name} diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js new file mode 100644 index 000000000..1225fe366 --- /dev/null +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js @@ -0,0 +1,80 @@ +import { useState } from "react"; +import { useSelector } from "react-redux"; + +const useOIPCHook = () => { + //OIPC State + const requestDetails = useSelector((state) => state.foiRequests.foiRequestDetail); + const stageOIPCData = (oipcData) => { + if (oipcData?.length > 0) { + return oipcData.map((item, index) => { + item.id = index; + return item; + }); + } else { + return [{ + id: 0, + oipcno: "", + reviewtypeid: null, + reasonid: null, + statusid: null, + isinquiry: false, + inquiryattributes: null, + receiveddate: "", + closeddate: "", + investigator: "", + outcomeid: null, + isjudicialreview: false, + issubsequentappeal: false, + }]; + } + } + const [oipcData, setOipcData] = useState(stageOIPCData(requestDetails.oipcdetails)); + + //OIPC Functions + const addOIPC = () => { + setOipcData((prev) => { + return [...prev, { + id: oipcData.length > 0 ? oipcData[oipcData.length - 1].id + 1 : 0, + oipcno: "", + reviewtypeid: null, + reasonid: null, + statusid: null, + isinquiry: false, + inquiryattributes: null, + receiveddate: "", + closeddate: "", + investigator: "", + outcomeid: null, + isjudicialreview: false, + issubsequentappeal: false, + }]; + }) + } + const removeOIPC = (oipcId) => { + setOipcData((prev) => { + const previousOIPCData = [...prev]; + return previousOIPCData.filter(oipc => oipcId !== oipc.id); + }); + } + const updateOIPC = (newOIPCObj) => { + setOipcData((prev) => { + const previousOIPCData = [...prev]; + return previousOIPCData.map((oipc) => { + if (oipc.id === newOIPCObj.id) { + return newOIPCObj; + } else { + return oipc; + } + }); + }); + } + + return { + oipcData, + addOIPC, + removeOIPC, + updateOIPC, + }; +}; + +export default useOIPCHook; \ No newline at end of file diff --git a/forms-flow-web/src/components/FOI/FOIRequest/utils.js b/forms-flow-web/src/components/FOI/FOIRequest/utils.js index f4aa33500..f608e6147 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/utils.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/utils.js @@ -321,9 +321,9 @@ export const checkValidationError = ( requiredRequestDetailsValues, requiredAxisDetails, isAddRequest, - currentrequestStatus + currentrequestStatus, + oipcData ) => { - return ( requiredApplicantDetails.firstName === "" || requiredApplicantDetails.lastName === "" || @@ -346,7 +346,11 @@ export const checkValidationError = ( .includes("select") || !requiredRequestDetailsValues.receivedDate || !requiredRequestDetailsValues.requestStartDate || - !requiredAxisDetails.axisRequestId + !requiredAxisDetails.axisRequestId || + oipcData.some((oipc) => { + return oipc.oipcno === "" || oipc.receiveddate === "" || oipc.reviewtypeid === null || oipc.reasonid === null || oipc.statusid === null || + oipc.inquiryattributes?.orderno === "" || oipc.inquiryattributes?.inquiryoutcomeid === null || oipc.inquiryattributes?.inquirydate === ""; + }) ); }; From 49ebfe6067ce56889e4025075b4bfd92fc125ee4 Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Thu, 23 Nov 2023 15:55:44 -0800 Subject: [PATCH 030/238] Create RequestFlag component --- .../FOI/customComponents/RequestFlag.js | 348 ++++++++++++++++++ .../FOI/customComponents/requestflag.scss | 78 ++++ 2 files changed, 426 insertions(+) create mode 100644 forms-flow-web/src/components/FOI/customComponents/RequestFlag.js create mode 100644 forms-flow-web/src/components/FOI/customComponents/requestflag.scss diff --git a/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js b/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js new file mode 100644 index 000000000..0cc461e70 --- /dev/null +++ b/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js @@ -0,0 +1,348 @@ +import React, { useEffect, useState } from "react"; +import "./requestflag.scss"; + +import OutlinedInput from "@material-ui/core/OutlinedInput"; +import InputLabel from "@mui/material/InputLabel"; +import MenuItem from "@material-ui/core/MenuItem"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faFlag } from "@fortawesome/free-regular-svg-icons"; +import { faFlag as faSolidFlag } from "@fortawesome/free-solid-svg-icons"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogContentText from "@material-ui/core/DialogContentText"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import CloseIcon from "@material-ui/icons/Close"; +import IconButton from "@material-ui/core/IconButton"; +import TextField from "@mui/material/TextField"; +import { useParams } from "react-router-dom"; +import { saveRequestDetails } from "../../../apiManager/services/FOI/foiRequestServices"; +import { toast } from "react-toastify"; +import { useDispatch } from "react-redux"; +import { + restrictRequest, + fetchFOIRequestDetailsWrapper, +} from "../../../apiManager/services/FOI/foiRequestServices"; +import { request } from "http"; +import { is } from "immutable"; + +//Types are: +//oipcreview +//phasedrelease +const RequestFlag = ({ type, requestDetails }) => { + const [isSelected, setIsSelected] = useState(requestDetails.isActive); + const [modalOpen, setModalOpen] = useState(false); + const [modalHeading, setModalHeading] = useState(""); + const [modalMessage, setModalMessage] = useState(""); + const [modalDescription, setModalDescription] = useState(""); + + const { requestId, ministryId } = useParams(); + + const dispatch = useDispatch(); + + + + // These need to be set for each type + let options; + let id; + let modalHeadingActive = ""; + let modalHeadingInactive = ""; + let modalMessageActive = ""; + let modalMessageInactive = ""; + let modalDescriptionActive = ""; + let modalDescriptionInactive = ""; + + let handleSaveForActive = () => {}; + let handleSaveForInactive = () => {}; + + // css + let iconClass; + let isSelectedBgClass; + let bgClass; + + console.log('options: ', options) + console.log('type: ', type) + switch (type) { + //Need to change heading, message, description for modals as well + case "oipcreview": + options = [ + { + value: true, + label: "OIPC Review", + disabled: false, + }, + { + value: false, + label: "No Review", + disabled: false, + }, + ]; + + id = "oipc-review-flag"; + iconClass = "oipc-review-icon"; + isSelectedBgClass = + "linear-gradient(to right, rgba(250,124,22,0.32) 80%, #fa7c16 0%)"; + bgClass = "linear-gradient(to right, #fff 80%, #fa7c16 0%)"; + + //when setting to active + modalHeadingActive = "OIPC Review"; + modalMessageActive = + "Are you sure you want to flag this request as OIPC review?"; + modalDescriptionActive = ( + + This will create a new OIPC review section on this request. + + ); + console.log('options: ', options) + + handleSaveForActive = () => { + console.log("setting to active"); + requestDetails.isoipcreview = true; + console.log(requestDetails); + }; + + //when setting to inactive + modalHeadingActive = "OIPC Review"; + modalMessageInactive = + "Are you sure you want to remove the OIPC review flag from this request?"; + modalDescriptionInactive = ( + + This will remove the OIPC review section from this request. + + ); + handleSaveForInactive = () => { + console.log("setting to inactive"); + requestDetails.isoipcreview = false; + console.log(requestDetails); + }; + break; + + case "phasedrelease": + options = [ + { + value: true, + label: "Phased Release", + disabled: false, + }, + { + value: false, + label: "Single Release", + disabled: false, + }, + ]; + + id = "phased-release-flag"; + iconClass = "phased-release-icon"; + isSelectedBgClass = + "linear-gradient(to right, rgba(146, 7, 183, 0.32) 80%, #9207b7 0%)"; + bgClass = "linear-gradient(to right, #fff 80%, #9207b7 0%)"; + + //when setting to active + modalHeadingActive = "Phased Release"; + modalMessageActive = + "Are you sure you want to flag this request as a Phased Release?"; + modalDescriptionActive = ( + This will tag the request as Phased Release. + ); + handleSaveForActive = () => { + console.log("setting to active"); + requestDetails.isphasedrelease = true; + console.log(requestDetails); + }; + + //when setting to inactive + modalHeadingInactive = "Single Release"; + modalMessageInactive = + "Are you sure you want to change this request to Single Release?"; + modalDescriptionInactive = ( + This will tag the request as Single Release. + ); + handleSaveForInactive = () => { + console.log("setting to inactive"); + requestDetails.isphasedrelease = false; + console.log(requestDetails); + }; + break; + } + + const handleValueChange = (e) => { + setModalOpen(true); + + if (e.target.value == true) { + setModalHeading(modalHeadingActive); + setModalMessage(modalMessageActive); + setModalDescription(modalDescriptionActive); + } else { + setModalHeading(modalHeadingInactive); + setModalMessage(modalMessageInactive); + setModalDescription(modalDescriptionInactive); + } + setIsSelected(e.target.value); + }; + + const handleClose = () => { + setModalOpen(false); + setIsSelected(requestDetails.isActive); + }; + + const handleSave = (e) => { + setModalOpen(false); + saveOipcReviewStatus(); + // if (isSelected) { + // handleSaveForActive(); + // } else { + // handleSaveForInactive(); + // } + }; + + const saveOipcReviewStatus = () => { + // dispatch(setFOILoader(setLoader)); + let updatedRequestDetails; + if (type == "oipcreview") { + updatedRequestDetails = { + ...requestDetails, + isoipcreview: isSelected, + }; + } else if (type == "phasedrelease") { + updatedRequestDetails = { + ...requestDetails, + isphasedrelease: isSelected, + }; + } + dispatch( + saveRequestDetails( + updatedRequestDetails, + -2, + requestId, + ministryId, + (err, res) => { + if (!err) { + toast.success("The request has been saved successfully.", { + position: "top-right", + autoClose: 3000, + hideProgressBar: true, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + }); + // const _state = getRequestState({ + // currentSelectedStatus, + // requestState, + // urlIndexCreateRequest, + // saveRequestObject, + // }); + // handleSaveRequest(_state, false, res.id); + // hasStatusRequestSaved(currentSelectedStatus); + } else { + toast.error( + "Temporarily unable to save your request. Please try again in a few minutes.", + { + position: "top-right", + autoClose: 3000, + hideProgressBar: true, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + } + ); + // handleSaveRequest(requestState, true, ""); + } + } + ) + ); + }; + + return ( + <> +
+
+
+ {isSelected ? ( + + ) : ( + + )} + {/* + Unrestricted + */} + } + disabled={false} + > + {options.map((option) => ( + + {option.label} + + ))} + +
+
+
+
+ { + console.log("onClose"); + }} + aria-labelledby="state-change-dialog-title" + aria-describedby="restricted-modal-text" + maxWidth={"md"} + fullWidth={true} + // id="state-change-dialog" + > + +

{modalHeading}

+ + Close + + +
+ + +
+
{modalMessage}
+
+ {modalDescription} +
+
+
+
+ + + + +
+
+ + ); +}; + +export default RequestFlag; diff --git a/forms-flow-web/src/components/FOI/customComponents/requestflag.scss b/forms-flow-web/src/components/FOI/customComponents/requestflag.scss new file mode 100644 index 000000000..4eb12f1e6 --- /dev/null +++ b/forms-flow-web/src/components/FOI/customComponents/requestflag.scss @@ -0,0 +1,78 @@ +.request-flag { + + margin-left: 15px; + + .request-flag-dropdown-all { + padding-top: 10px; + display: flex; + min-width: 200px !important; + } + + .oipc-review-icon{ + color: #fa7c16; + padding-left: 14px; + margin-top: 3px; + } + + .phased-release-icon{ + color: #9207b7; + padding-left: 14px; + margin-top: 3px; + } + + .restrict-label { + border: 1px solid #a0192f; + width: 100px; + border-radius: 40px 0 0 40px; + } + + .request-flag-select{ + border: 1px solid #a0192f; + //padding-top: 8px; + //width:40px; + height: 40px; + border-radius: 40px; + padding-left: 3px; + //background: linear-gradient(to right, rgba(160,25,47,0.32) 80%, #a0192f 0%); + } + + + .request-flag-dropdown { + color: black !important; + width: 155px; + padding-left: 10px; + } + + .request-flag-dropdown .MuiSelect-icon { + color: white !important; + } + + .request-flag-dropdown .MuiOutlinedInput-notchedOutline { + border: none !important; + } + + .request-flag-dropdown .MuiInputBase-input, + .request-flag-dropdown .MuiOutlinedInput-input { + padding: 0px !important + } + + @media (max-width: 1242px) { + margin-left: 0px; + } + +} + +#restricted-modal-text{ + margin: 15px 65px; + display: block; + color: #000; +} + +.modal-msg { + text-align: center; +} + +.modal-msg-description { + padding-top: 25px; +} + From 9276b0eaa435f8f9ff885a45b6d5380cc3f0d475 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Thu, 23 Nov 2023 17:33:24 -0800 Subject: [PATCH 031/238] Request Object Adjusted. Testing of save to BE WIP + refactor + styling --- .../components/FOI/FOIRequest/FOIRequest.js | 9 ++++ .../FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 47 +++++++++++-------- 2 files changed, 37 insertions(+), 19 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index 7132275fe..59a339187 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -775,7 +775,16 @@ const FOIRequest = React.memo(({ userDetail }) => { }; } }, [editorChange]); + + //useEffect to update saveReq object with oipc data + useEffect(() => { + setSaveRequestObject((prev) => { + return {...prev, oipcdetails: oipcData} + }) + }, [oipcData]); + console.log(saveRequestObject) + const tabclick = (param) => { if (param === "Comments") { sessionStorage.setItem("foicommentcategory", 1); diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index c1121bf93..fe98db8da 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -25,16 +25,39 @@ const OIPCItem = (props) => { closeddate: oipcObj?.closeddate, investigator: oipcObj?.investigator, outcomeid: oipcObj?.outcomeid, - isjudicialreview: oipcObj?.isjudicialreview, - reviewtypeName: oipcObj?.reviewtypeName, - reasonName: oipcObj?.reasonName, - statusName: oipcObj?.statusName, - outcomeName: oipcObj?.outcomeName, + isjudicialreview: oipcObj?.isjudicialreview, + issubsequentappeal: oipcObj?.issubsequentappeal, + reviewtypeName: "", + reasonName: "", + statusName: "", + outcomeName: "", }); console.log(oipc); //Functions + const generateNamesFromOIPCId = (oipcObj) => { + const reviewtype = oipcReviewtypes.find(reviewtype => reviewtype.reviewtypeid === oipcObj.reviewtypeid && reviewtype.reasonid === oipcObj.reasonid); + const status = oipcStatuses.find(status => status.statusid === oipcObj.statusid); + const outcome = oipcOutcomes.find(outcome => outcome.outcomeid === oipcObj.outcomeid); + + setOipc((prev) => { + return {...prev, reviewtypeName: reviewtype ? reviewtype.type_name : ""} + }) + setOipc((prev) => { + return {...prev, statusName: status ? status.type_name : ""} + }) + setOipc((prev) => { + return {...prev, outcomeName: outcome ? outcome.type_name : ""} + }) + setOipc((prev) => { + return {...prev, reasonName: reviewtype ? reviewtype.reason_name : ""} + }) + } + const uniqueReviewTypes = (oipcReviewTypes) => { + const uniqeValues = {}; + return oipcReviewTypes.filter(reviewtype => !uniqeValues[reviewtype.type_name] && (uniqeValues[reviewtype.type_name] = true)); + } const handleReviewType = (value) => { const newOIPCObj = oipc; newOIPCObj.reviewtypeid = value; @@ -113,20 +136,6 @@ const OIPCItem = (props) => { } updateOIPC(newOIPCObj); } - const generateNamesFromOIPCId = (oipcObj) => { - const reviewtype = oipcReviewtypes.find(reviewtype => reviewtype.reviewtypeid === oipcObj.reviewtypeid && reviewtype.reasonid === oipcObj.reasonid); - const status = oipcStatuses.find(status => status.statusid === oipcObj.statusid); - const outcome = oipcOutcomes.find(outcome => outcome.outcomeid === oipcObj.outcomeid); - - oipcObj.reviewtypeName = reviewtype ? reviewtype.type_name : ""; - oipcObj.statusName = status ? status.name : ""; - oipcObj.outcomeName = outcome ? outcome.name : ""; - oipcObj.reasonName = reviewtype ? reviewtype.reason_name : ""; - } - const uniqueReviewTypes = (oipcReviewTypes) => { - const uniqeValues = {}; - return oipcReviewTypes.filter(reviewtype => !uniqeValues[reviewtype.type_name] && (uniqeValues[reviewtype.type_name] = true)); - } //useEffect to create name attributes using id's for oipcObject useEffect(() => { From 1d61bd65d403e2940125c10eae71397201e7f87a Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Fri, 24 Nov 2023 15:42:03 -0800 Subject: [PATCH 032/238] Backend integration completed. WIP remaining stories/validations + refactor + styling finalization --- .../FOI/FOIRequest/BottomButtonGroup/index.js | 8 +++-- .../components/FOI/FOIRequest/FOIRequest.js | 12 ++------ .../OIPCDetails/OIPCDetailsList.jsx | 2 ++ .../FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 29 ++++++++++++++----- .../FOI/FOIRequest/OIPCDetails/oipcHook.js | 20 +++++++++---- .../src/components/FOI/FOIRequest/utils.js | 6 ++-- 6 files changed, 48 insertions(+), 29 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/BottomButtonGroup/index.js b/forms-flow-web/src/components/FOI/FOIRequest/BottomButtonGroup/index.js index 5c301c061..ef9ba63d5 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/BottomButtonGroup/index.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/BottomButtonGroup/index.js @@ -75,7 +75,8 @@ const BottomButtonGroup = React.memo( requestState, axisSyncedData, axisMessage, - attachmentsArray + attachmentsArray, + oipcData, }) => { /** * Bottom Button Group of Review request Page @@ -117,7 +118,10 @@ const BottomButtonGroup = React.memo( if (urlIndexCreateRequest > -1) { saveRequestObject.requeststatusid = StateEnum.intakeinprogress.id; setIsAddRequest(false); - } + } + //add oipc Data + saveRequestObject.oipcdetails = oipcData; + console.log(saveRequestObject) dispatch(setFOILoader(setLoader)) dispatch( saveRequestDetails( diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index 59a339187..968049575 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -776,15 +776,6 @@ const FOIRequest = React.memo(({ userDetail }) => { } }, [editorChange]); - //useEffect to update saveReq object with oipc data - useEffect(() => { - setSaveRequestObject((prev) => { - return {...prev, oipcdetails: oipcData} - }) - }, [oipcData]); - - console.log(saveRequestObject) - const tabclick = (param) => { if (param === "Comments") { sessionStorage.setItem("foicommentcategory", 1); @@ -1230,7 +1221,7 @@ const FOIRequest = React.memo(({ userDetail }) => { divisions={requestDetails.divisions} /> )} - {showOIPCDetails && requestDetails.oipcdetails && ( + {showOIPCDetails && requestDetails.isoipcreview && requestState && requestState.toLowerCase() !== StateEnum.intakeinprogress.name.toLowerCase() && ( { axisSyncedData={axisSyncedData} axisMessage={axisMessage} attachmentsArray={requestAttachments} + oipcData={oipcData} /> diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx index dc5cb8b72..f183df533 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx @@ -6,6 +6,8 @@ import { faTrash } from '@fortawesome/free-solid-svg-icons'; const OIPCDetailsList = (props) => { const {oipcData, removeOIPC, updateOIPC} = props; + + console.log("COMPONENT", oipcData) const OIPCItems = oipcData?.map((oipcObj, index) => { return ( diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index fe98db8da..b6c158685 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -27,10 +27,10 @@ const OIPCItem = (props) => { outcomeid: oipcObj?.outcomeid, isjudicialreview: oipcObj?.isjudicialreview, issubsequentappeal: oipcObj?.issubsequentappeal, - reviewtypeName: "", - reasonName: "", - statusName: "", - outcomeName: "", + reviewtypeName: oipcObj?.reviewtype, + reasonName: oipcObj?.reason, + statusName: oipcObj?.status, + outcomeName: oipcObj?.outcome, }); console.log(oipc); @@ -62,41 +62,49 @@ const OIPCItem = (props) => { const newOIPCObj = oipc; newOIPCObj.reviewtypeid = value; newOIPCObj.reasonid = null; + setOipc(newOIPCObj); updateOIPC(newOIPCObj); } const handleOIPCNumber = (value) => { const newOIPCObj = oipc; newOIPCObj.oipcno = value; + setOipc(newOIPCObj); updateOIPC(newOIPCObj); } const handleReceivedDate = (value) => { const newOIPCObj = oipc; newOIPCObj.receiveddate = value; + setOipc(newOIPCObj); updateOIPC(newOIPCObj); } const handleClosedDate = (value) => { const newOIPCObj = oipc; newOIPCObj.closeddate = value; + setOipc(newOIPCObj); updateOIPC(newOIPCObj); } const handleReason = (value) => { const newOIPCObj = oipc; newOIPCObj.reasonid = value; + setOipc(newOIPCObj); updateOIPC(newOIPCObj); } const handleStatus = (value) => { const newOIPCObj = oipc; newOIPCObj.statusid = value; + setOipc(newOIPCObj); updateOIPC(newOIPCObj); } const handleInvestiagtor = (value) => { const newOIPCObj = oipc; newOIPCObj.investigator = value; + setOipc(newOIPCObj); updateOIPC(newOIPCObj); } const handleOutcome = (value) => { const newOIPCObj = oipc; newOIPCObj.outcomeid = value; + setOipc(newOIPCObj); updateOIPC(newOIPCObj); } const handleInquiry = (value) => { @@ -111,16 +119,19 @@ const OIPCItem = (props) => { }; } newOIPCObj.isinquiry = value; + setOipc(newOIPCObj); updateOIPC(newOIPCObj); } const handleJudicalReview = (value) => { const newOIPCObj = oipc; newOIPCObj.isjudicialreview = value; + setOipc(newOIPCObj); updateOIPC(newOIPCObj); } const handleSubsequentAppeal = (value) => { const newOIPCObj = oipc; newOIPCObj.issubsequentappeal = value; + setOipc(newOIPCObj); updateOIPC(newOIPCObj); } const handleInquiryFields = (value, attribute) => { @@ -134,12 +145,13 @@ const OIPCItem = (props) => { if (attribute === "INQUIRYOUTCOME") { newOIPCObj.inquiryattributes.inquiryoutcomeid = value; } + setOipc(newOIPCObj); updateOIPC(newOIPCObj); } - //useEffect to create name attributes using id's for oipcObject useEffect(() => { - generateNamesFromOIPCId(oipcObj); + setOipc(oipcObj); + generateNamesFromOIPCId(oipc); }, [oipcObj]) return ( @@ -163,12 +175,13 @@ const OIPCItem = (props) => { label="Received Date" variant="outlined" required={true} + defaultValue="" value={oipc.receiveddate} onChange = {(event) => handleReceivedDate(event.target.value)} InputLabelProps={{ shrink: true }} - InputProps={{inputProps: { max: oipc.receiveddate || formatDate(new Date())} }} + InputProps={{inputProps: { max: formatDate(new Date())} }} type="date" - error={oipc.receiveddate === ""} + error={oipc.receiveddate === null} />
diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js index 1225fe366..0fb9d8704 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js @@ -1,4 +1,4 @@ -import { useState } from "react"; +import { useState, useEffect } from "react"; import { useSelector } from "react-redux"; const useOIPCHook = () => { @@ -19,8 +19,8 @@ const useOIPCHook = () => { statusid: null, isinquiry: false, inquiryattributes: null, - receiveddate: "", - closeddate: "", + receiveddate: null, + closeddate: null, investigator: "", outcomeid: null, isjudicialreview: false, @@ -28,7 +28,14 @@ const useOIPCHook = () => { }]; } } - const [oipcData, setOipcData] = useState(stageOIPCData(requestDetails.oipcdetails)); + const [oipcData, setOipcData] = useState(requestDetails.oipcdetails); + + useEffect(() => { + const stagedOIPCData = stageOIPCData(requestDetails.oipcdetails); + setOipcData(stagedOIPCData); + }, [requestDetails]) + + console.log("HOOK", oipcData) //OIPC Functions const addOIPC = () => { @@ -41,8 +48,8 @@ const useOIPCHook = () => { statusid: null, isinquiry: false, inquiryattributes: null, - receiveddate: "", - closeddate: "", + receiveddate: null, + closeddate: null, investigator: "", outcomeid: null, isjudicialreview: false, @@ -74,6 +81,7 @@ const useOIPCHook = () => { addOIPC, removeOIPC, updateOIPC, + stageOIPCData, }; }; diff --git a/forms-flow-web/src/components/FOI/FOIRequest/utils.js b/forms-flow-web/src/components/FOI/FOIRequest/utils.js index f608e6147..b5398f082 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/utils.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/utils.js @@ -347,10 +347,10 @@ export const checkValidationError = ( !requiredRequestDetailsValues.receivedDate || !requiredRequestDetailsValues.requestStartDate || !requiredAxisDetails.axisRequestId || - oipcData.some((oipc) => { - return oipc.oipcno === "" || oipc.receiveddate === "" || oipc.reviewtypeid === null || oipc.reasonid === null || oipc.statusid === null || + (oipcData.length > 0 && oipcData.some((oipc) => { + return oipc.oipcno === "" || oipc.receiveddate === null || oipc.reviewtypeid === null || oipc.reasonid === null || oipc.statusid === null || oipc.inquiryattributes?.orderno === "" || oipc.inquiryattributes?.inquiryoutcomeid === null || oipc.inquiryattributes?.inquirydate === ""; - }) + })) ); }; From 46795f439a442fb7c30cfd7674b2e1ea53677600 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Fri, 24 Nov 2023 16:26:13 -0800 Subject: [PATCH 033/238] Date picker validation completed --- .../FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index b6c158685..bcb2c5bef 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -32,8 +32,6 @@ const OIPCItem = (props) => { statusName: oipcObj?.status, outcomeName: oipcObj?.outcome, }); - - console.log(oipc); //Functions const generateNamesFromOIPCId = (oipcObj) => { @@ -176,7 +174,7 @@ const OIPCItem = (props) => { variant="outlined" required={true} defaultValue="" - value={oipc.receiveddate} + value={oipc.receiveddate ? formatDate(new Date(oipc.receiveddate)) : null} onChange = {(event) => handleReceivedDate(event.target.value)} InputLabelProps={{ shrink: true }} InputProps={{inputProps: { max: formatDate(new Date())} }} @@ -268,10 +266,9 @@ const OIPCItem = (props) => { fullWidth label="Closed Date" variant="outlined" - value={oipc.closeddate} + value={oipc.closeddate ? formatDate(new Date(oipc.closeddate)) : null} onChange = {(event) => handleClosedDate(event.target.value)} InputLabelProps={{ shrink: true }} - InputProps={{inputProps: { max: oipc.closeddate || formatDate(new Date())} }} type="date" /> @@ -331,10 +328,10 @@ const OIPCItem = (props) => { label="Comply By Date" variant="outlined" required={true} - value={oipc.inquiryattributes.inquirydate} + value={oipc.inquiryattributes.inquirydate ? formatDate(new Date(oipc.inquiryattributes.inquirydate)) : null} onChange = {(event) => handleInquiryFields(event.target.value, "COMPLYDATE")} InputLabelProps={{ shrink: true }} - InputProps={{inputProps: { min: oipc.receiveddate } }} + InputProps={{inputProps: { min: oipc.receiveddate ? formatDate(new Date(oipc.receiveddate)) : null } }} type="date" error={oipc.inquiryattributes.inquirydate === ""} /> From 5f22beff1cb6ccf5cf9435af3e3f8a35ce5b48eb Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Fri, 24 Nov 2023 17:19:32 -0800 Subject: [PATCH 034/238] Bug fixes for communication between backend and frontend (getting/posting) --- .../FOI/FOIRequest/BottomButtonGroup/index.js | 1 - .../FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 13 +++++++------ .../src/components/FOI/FOIRequest/utils.js | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/BottomButtonGroup/index.js b/forms-flow-web/src/components/FOI/FOIRequest/BottomButtonGroup/index.js index ef9ba63d5..19678e50b 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/BottomButtonGroup/index.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/BottomButtonGroup/index.js @@ -121,7 +121,6 @@ const BottomButtonGroup = React.memo( } //add oipc Data saveRequestObject.oipcdetails = oipcData; - console.log(saveRequestObject) dispatch(setFOILoader(setLoader)) dispatch( saveRequestDetails( diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index bcb2c5bef..a653305a9 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -111,9 +111,9 @@ const OIPCItem = (props) => { newOIPCObj.inquiryattributes = null; } else { newOIPCObj.inquiryattributes = { - inquirydate: "", + inquirydate: null, orderno: "", - inquiryoutcomeid: null, + inquiryoutcome: null, }; } newOIPCObj.isinquiry = value; @@ -141,7 +141,7 @@ const OIPCItem = (props) => { newOIPCObj.inquiryattributes.orderno = value; } if (attribute === "INQUIRYOUTCOME") { - newOIPCObj.inquiryattributes.inquiryoutcomeid = value; + newOIPCObj.inquiryattributes.inquiryoutcome = value; } setOipc(newOIPCObj); updateOIPC(newOIPCObj); @@ -269,6 +269,7 @@ const OIPCItem = (props) => { value={oipc.closeddate ? formatDate(new Date(oipc.closeddate)) : null} onChange = {(event) => handleClosedDate(event.target.value)} InputLabelProps={{ shrink: true }} + InputProps={{inputProps: { max: formatDate(new Date())} }} type="date" /> @@ -333,7 +334,7 @@ const OIPCItem = (props) => { InputLabelProps={{ shrink: true }} InputProps={{inputProps: { min: oipc.receiveddate ? formatDate(new Date(oipc.receiveddate)) : null } }} type="date" - error={oipc.inquiryattributes.inquirydate === ""} + error={oipc.inquiryattributes.inquirydate === null} /> @@ -356,9 +357,9 @@ const OIPCItem = (props) => { variant="outlined" onChange = {(event) => handleInquiryFields(event.target.value, "INQUIRYOUTCOME")} fullWidth - value={oipc.inquiryattributes.inquiryoutcomeid} + value={oipc.inquiryattributes.inquiryoutcome} label="Outcome" - error={oipc.inquiryattributes.inquiryoutcomeid === null} + error={oipc.inquiryattributes.inquiryoutcome === null} > {oipcInquiryoutcomes.map((inquiryoutcome) => { return {inquiryoutcome.name} diff --git a/forms-flow-web/src/components/FOI/FOIRequest/utils.js b/forms-flow-web/src/components/FOI/FOIRequest/utils.js index b5398f082..b73988d48 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/utils.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/utils.js @@ -349,7 +349,7 @@ export const checkValidationError = ( !requiredAxisDetails.axisRequestId || (oipcData.length > 0 && oipcData.some((oipc) => { return oipc.oipcno === "" || oipc.receiveddate === null || oipc.reviewtypeid === null || oipc.reasonid === null || oipc.statusid === null || - oipc.inquiryattributes?.orderno === "" || oipc.inquiryattributes?.inquiryoutcomeid === null || oipc.inquiryattributes?.inquirydate === ""; + oipc.inquiryattributes?.orderno === "" || oipc.inquiryattributes?.inquiryoutcome === null || oipc.inquiryattributes?.inquirydate === null; })) ); }; From c518e51c105630a1bc4a0bbb2d0809bf3f6cd353 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Sat, 25 Nov 2023 14:45:47 -0800 Subject: [PATCH 035/238] Added further deletion validation to OIPC reviews. WIP outcome validation + BE Testing + refactor/final styling --- .../FOI/FOIRequest/BottomButtonGroup/index.js | 9 ++- .../components/FOI/FOIRequest/FOIRequest.js | 1 + .../FOI/FOIRequest/OIPCDetails/Index.jsx | 1 + .../OIPCDetails/OIPCDetailsList.jsx | 12 +--- .../FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 51 +++++++-------- .../OIPCDetails/RemoveOIPCModal.jsx | 62 +++++++++++++++++++ .../src/components/FOI/FOIRequest/utils.js | 5 +- 7 files changed, 96 insertions(+), 45 deletions(-) create mode 100644 forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/RemoveOIPCModal.jsx diff --git a/forms-flow-web/src/components/FOI/FOIRequest/BottomButtonGroup/index.js b/forms-flow-web/src/components/FOI/FOIRequest/BottomButtonGroup/index.js index 19678e50b..1b2d06b3c 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/BottomButtonGroup/index.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/BottomButtonGroup/index.js @@ -118,9 +118,12 @@ const BottomButtonGroup = React.memo( if (urlIndexCreateRequest > -1) { saveRequestObject.requeststatusid = StateEnum.intakeinprogress.id; setIsAddRequest(false); - } - //add oipc Data - saveRequestObject.oipcdetails = oipcData; + } + + //add oipc Data to save request object + saveRequestObject.oipcdetails = oipcData; + if (oipcData.length <= 0) saveRequestObject.isoipcreview = false; + dispatch(setFOILoader(setLoader)) dispatch( saveRequestDetails( diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index 968049575..cf024584b 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -665,6 +665,7 @@ const FOIRequest = React.memo(({ userDetail }) => { isAddRequest, _currentrequestStatus, oipcData, + requestDetails.isoipcreview, ); const classes = useStyles(); diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx index c7a6985b1..2d02e79e8 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx @@ -10,6 +10,7 @@ import { faCirclePlus } from '@fortawesome/free-solid-svg-icons'; const OIPCDetails = (props) => { const { oipcData, addOIPC, removeOIPC, updateOIPC } = props; + //Styling const useStyles = makeStyles({ heading: { diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx index f183df533..afa6f2fa8 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx @@ -1,23 +1,15 @@ import OIPCItem from "./OIPCItem"; import Divider from '@material-ui/core/Divider'; import './oipcdetails.scss'; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { faTrash } from '@fortawesome/free-solid-svg-icons'; const OIPCDetailsList = (props) => { const {oipcData, removeOIPC, updateOIPC} = props; console.log("COMPONENT", oipcData) - const OIPCItems = oipcData?.map((oipcObj, index) => { return ( - <> -
- -
- + <> + {index !== (oipcData.length - 1) && } ); diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index a653305a9..27cd1aac1 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -2,9 +2,12 @@ import { TextField, FormControlLabel, MenuItem, Grid, Checkbox } from '@material import { useState, useEffect } from "react"; import { formatDate } from "../../../../helper/FOI/helper"; import { useSelector } from "react-redux"; +import RemoveOIPCModal from './RemoveOIPCModal'; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faTrash } from '@fortawesome/free-solid-svg-icons'; const OIPCItem = (props) => { - const {oipcObj, updateOIPC} = props; + const {oipcObj, updateOIPC, removeOIPC} = props; //App State const oipcOutcomes = useSelector(state=> state.foiRequests.oipcOutcomes); @@ -13,25 +16,8 @@ const OIPCItem = (props) => { const oipcInquiryoutcomes = useSelector(state=> state.foiRequests.oipcInquiryoutcomes); //Local State - const [oipc, setOipc] = useState({ - id: oipcObj?.id, - oipcno: oipcObj?.oipcno, - reviewtypeid: oipcObj?.reviewtypeid, - reasonid: oipcObj?.reasonid, - statusid: oipcObj?.statusid, - isinquiry: oipcObj?.isinquiry, - inquiryattributes: oipcObj?.inquiryattributes, - receiveddate: oipcObj?.receiveddate, - closeddate: oipcObj?.closeddate, - investigator: oipcObj?.investigator, - outcomeid: oipcObj?.outcomeid, - isjudicialreview: oipcObj?.isjudicialreview, - issubsequentappeal: oipcObj?.issubsequentappeal, - reviewtypeName: oipcObj?.reviewtype, - reasonName: oipcObj?.reason, - statusName: oipcObj?.status, - outcomeName: oipcObj?.outcome, - }); + const [oipc, setOipc] = useState(oipcObj); + const [showDeleteModal, setShowDeleteModal] = useState(false); //Functions const generateNamesFromOIPCId = (oipcObj) => { @@ -153,18 +139,24 @@ const OIPCItem = (props) => { }, [oipcObj]) return ( - <> + <> +
+ +
+ {showDeleteModal && } handleOIPCNumber(event.target.value)} InputLabelProps={{ shrink: true }} error={oipc.oipcno === ""} + required /> @@ -172,14 +164,13 @@ const OIPCItem = (props) => { fullWidth label="Received Date" variant="outlined" - required={true} - defaultValue="" value={oipc.receiveddate ? formatDate(new Date(oipc.receiveddate)) : null} onChange = {(event) => handleReceivedDate(event.target.value)} InputLabelProps={{ shrink: true }} InputProps={{inputProps: { max: formatDate(new Date())} }} type="date" error={oipc.receiveddate === null} + required /> @@ -191,8 +182,8 @@ const OIPCItem = (props) => { value={oipc.reviewtypeid} label="Review Type" onChange={(event) => handleReviewType(event.target.value)} - required={true} error={oipc.reviewtypeid === null} + required > {uniqueReviewTypes(oipcReviewtypes).map((reviewtype) => { return {reviewtype.type_name} @@ -208,8 +199,8 @@ const OIPCItem = (props) => { value={oipc.reasonid} label="Reason" onChange = {(event) => handleReason(event.target.value)} - required={true} error={oipc.reasonid === null} + required > {oipc.reviewtypeid ? oipcReviewtypes.map((reviewtype) => { @@ -228,8 +219,8 @@ const OIPCItem = (props) => { value={oipc.statusid} label="Status" onChange = {(event) => handleStatus(event.target.value)} - required={true} error={oipc.statusid === null} + required > {oipcStatuses.map((status) => { return {status.name} @@ -328,13 +319,13 @@ const OIPCItem = (props) => { fullWidth label="Comply By Date" variant="outlined" - required={true} value={oipc.inquiryattributes.inquirydate ? formatDate(new Date(oipc.inquiryattributes.inquirydate)) : null} onChange = {(event) => handleInquiryFields(event.target.value, "COMPLYDATE")} InputLabelProps={{ shrink: true }} InputProps={{inputProps: { min: oipc.receiveddate ? formatDate(new Date(oipc.receiveddate)) : null } }} type="date" error={oipc.inquiryattributes.inquirydate === null} + required /> @@ -342,24 +333,24 @@ const OIPCItem = (props) => { fullWidth label="Order No" variant="outlined" - required={true} value={oipc.inquiryattributes.orderno} onChange = {(event) => handleInquiryFields(event.target.value, "ORDERNO")} InputLabelProps={{ shrink: true }} error={oipc.inquiryattributes.orderno === ""} + required /> handleInquiryFields(event.target.value, "INQUIRYOUTCOME")} fullWidth value={oipc.inquiryattributes.inquiryoutcome} label="Outcome" error={oipc.inquiryattributes.inquiryoutcome === null} + required > {oipcInquiryoutcomes.map((inquiryoutcome) => { return {inquiryoutcome.name} diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/RemoveOIPCModal.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/RemoveOIPCModal.jsx new file mode 100644 index 000000000..a63c8f1ae --- /dev/null +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/RemoveOIPCModal.jsx @@ -0,0 +1,62 @@ +import Dialog from '@material-ui/core/Dialog'; +import DialogActions from '@material-ui/core/DialogActions'; +import DialogContent from '@material-ui/core/DialogContent'; +import DialogContentText from '@material-ui/core/DialogContentText'; +import DialogTitle from '@material-ui/core/DialogTitle'; +import CloseIcon from '@material-ui/icons/Close'; +import IconButton from '@material-ui/core/IconButton'; + +const RemoveOIPCModal= ({ + showModal, + removeOIPC, + setShowDeleteModal, + oipcid, +}) =>{ + + const handleSave = () => { + setShowDeleteModal(false); + removeOIPC(oipcid) + }; + const handleClose = () => { + setShowDeleteModal(false); + }; + + return ( +
+ + +

Remove OIPC

+ + Close + + +
+ + + + Are you sure you want to delete this OIPC Review? + + + + + + + +
+
+ ); +}; + +export default RemoveOIPCModal; diff --git a/forms-flow-web/src/components/FOI/FOIRequest/utils.js b/forms-flow-web/src/components/FOI/FOIRequest/utils.js index b73988d48..f71148f4b 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/utils.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/utils.js @@ -322,7 +322,8 @@ export const checkValidationError = ( requiredAxisDetails, isAddRequest, currentrequestStatus, - oipcData + oipcData, + isOipcReview ) => { return ( requiredApplicantDetails.firstName === "" || @@ -347,7 +348,7 @@ export const checkValidationError = ( !requiredRequestDetailsValues.receivedDate || !requiredRequestDetailsValues.requestStartDate || !requiredAxisDetails.axisRequestId || - (oipcData.length > 0 && oipcData.some((oipc) => { + (oipcData.length > 0 && isOipcReview && oipcData.some((oipc) => { return oipc.oipcno === "" || oipc.receiveddate === null || oipc.reviewtypeid === null || oipc.reasonid === null || oipc.statusid === null || oipc.inquiryattributes?.orderno === "" || oipc.inquiryattributes?.inquiryoutcome === null || oipc.inquiryattributes?.inquirydate === null; })) From 9549d512ec7710adb3887800793aad6faaec5eb4 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Mon, 27 Nov 2023 10:45:45 -0800 Subject: [PATCH 036/238] code adjustment --- .../FOI/FOIRequest/OIPCDetails/oipcHook.js | 48 ++++++++++--------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js index 0fb9d8704..d9fb732a4 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js @@ -4,34 +4,38 @@ import { useSelector } from "react-redux"; const useOIPCHook = () => { //OIPC State const requestDetails = useSelector((state) => state.foiRequests.foiRequestDetail); - const stageOIPCData = (oipcData) => { - if (oipcData?.length > 0) { - return oipcData.map((item, index) => { - item.id = index; - return item; - }); + const stageOIPCData = (isoipcreview, oipcData) => { + if (isoipcreview) { + if (oipcData?.length > 0) { + return oipcData.map((item, index) => { + item.id = index; + return item; + }); + } else { + return [{ + id: 0, + oipcno: "", + reviewtypeid: null, + reasonid: null, + statusid: null, + isinquiry: false, + inquiryattributes: null, + receiveddate: null, + closeddate: null, + investigator: "", + outcomeid: null, + isjudicialreview: false, + issubsequentappeal: false, + }]; + } } else { - return [{ - id: 0, - oipcno: "", - reviewtypeid: null, - reasonid: null, - statusid: null, - isinquiry: false, - inquiryattributes: null, - receiveddate: null, - closeddate: null, - investigator: "", - outcomeid: null, - isjudicialreview: false, - issubsequentappeal: false, - }]; + return []; } } const [oipcData, setOipcData] = useState(requestDetails.oipcdetails); useEffect(() => { - const stagedOIPCData = stageOIPCData(requestDetails.oipcdetails); + const stagedOIPCData = stageOIPCData(requestDetails.isoipcreview, requestDetails.oipcdetails); setOipcData(stagedOIPCData); }, [requestDetails]) From aace890e3152a77d432b7bbf73c1e867e0b669d6 Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Mon, 27 Nov 2023 11:10:47 -0800 Subject: [PATCH 037/238] Update requestflag component --- .../FOI/customComponents/RequestFlag.js | 55 ++++--------------- 1 file changed, 10 insertions(+), 45 deletions(-) diff --git a/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js b/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js index 0cc461e70..d29c9ece9 100644 --- a/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js +++ b/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js @@ -25,12 +25,13 @@ import { } from "../../../apiManager/services/FOI/foiRequestServices"; import { request } from "http"; import { is } from "immutable"; +import { setFOIUpdateLoader } from "../../../actions/FOI/foiRequestActions"; //Types are: //oipcreview //phasedrelease -const RequestFlag = ({ type, requestDetails }) => { - const [isSelected, setIsSelected] = useState(requestDetails.isActive); +const RequestFlag = ({ isActive, type, requestDetails }) => { + const [isSelected, setIsSelected] = useState(isActive || false); const [modalOpen, setModalOpen] = useState(false); const [modalHeading, setModalHeading] = useState(""); const [modalMessage, setModalMessage] = useState(""); @@ -60,8 +61,6 @@ const RequestFlag = ({ type, requestDetails }) => { let isSelectedBgClass; let bgClass; - console.log('options: ', options) - console.log('type: ', type) switch (type) { //Need to change heading, message, description for modals as well case "oipcreview": @@ -93,13 +92,6 @@ const RequestFlag = ({ type, requestDetails }) => { This will create a new OIPC review section on this request. ); - console.log('options: ', options) - - handleSaveForActive = () => { - console.log("setting to active"); - requestDetails.isoipcreview = true; - console.log(requestDetails); - }; //when setting to inactive modalHeadingActive = "OIPC Review"; @@ -110,11 +102,6 @@ const RequestFlag = ({ type, requestDetails }) => { This will remove the OIPC review section from this request. ); - handleSaveForInactive = () => { - console.log("setting to inactive"); - requestDetails.isoipcreview = false; - console.log(requestDetails); - }; break; case "phasedrelease": @@ -144,11 +131,6 @@ const RequestFlag = ({ type, requestDetails }) => { modalDescriptionActive = ( This will tag the request as Phased Release. ); - handleSaveForActive = () => { - console.log("setting to active"); - requestDetails.isphasedrelease = true; - console.log(requestDetails); - }; //when setting to inactive modalHeadingInactive = "Single Release"; @@ -157,11 +139,6 @@ const RequestFlag = ({ type, requestDetails }) => { modalDescriptionInactive = ( This will tag the request as Single Release. ); - handleSaveForInactive = () => { - console.log("setting to inactive"); - requestDetails.isphasedrelease = false; - console.log(requestDetails); - }; break; } @@ -182,21 +159,15 @@ const RequestFlag = ({ type, requestDetails }) => { const handleClose = () => { setModalOpen(false); - setIsSelected(requestDetails.isActive); + setIsSelected(isActive); }; const handleSave = (e) => { setModalOpen(false); saveOipcReviewStatus(); - // if (isSelected) { - // handleSaveForActive(); - // } else { - // handleSaveForInactive(); - // } }; const saveOipcReviewStatus = () => { - // dispatch(setFOILoader(setLoader)); let updatedRequestDetails; if (type == "oipcreview") { updatedRequestDetails = { @@ -209,15 +180,16 @@ const RequestFlag = ({ type, requestDetails }) => { isphasedrelease: isSelected, }; } + //dispatch loader dispatch( saveRequestDetails( updatedRequestDetails, - -2, + -2, //not an add request requestId, ministryId, (err, res) => { if (!err) { - toast.success("The request has been saved successfully.", { + toast.success("The OIPC review status has been successfully updated.", { position: "top-right", autoClose: 3000, hideProgressBar: true, @@ -226,17 +198,10 @@ const RequestFlag = ({ type, requestDetails }) => { draggable: true, progress: undefined, }); - // const _state = getRequestState({ - // currentSelectedStatus, - // requestState, - // urlIndexCreateRequest, - // saveRequestObject, - // }); - // handleSaveRequest(_state, false, res.id); - // hasStatusRequestSaved(currentSelectedStatus); + dispatch(fetchFOIRequestDetailsWrapper(requestId, ministryId)); } else { toast.error( - "Temporarily unable to save your request. Please try again in a few minutes.", + "Temporarily unable to update the OIPC review status. Please try again in a few minutes.", { position: "top-right", autoClose: 3000, @@ -247,7 +212,7 @@ const RequestFlag = ({ type, requestDetails }) => { progress: undefined, } ); - // handleSaveRequest(requestState, true, ""); + setIsSelected(isActive || false); } } ) From 912d9c91b41055870802097de0ad28856c478953 Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Mon, 27 Nov 2023 11:14:22 -0800 Subject: [PATCH 038/238] Remove unused imports --- .../components/FOI/customComponents/RequestFlag.js | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js b/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js index d29c9ece9..abfc21310 100644 --- a/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js +++ b/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js @@ -1,8 +1,7 @@ -import React, { useEffect, useState } from "react"; +import { useState } from "react"; import "./requestflag.scss"; import OutlinedInput from "@material-ui/core/OutlinedInput"; -import InputLabel from "@mui/material/InputLabel"; import MenuItem from "@material-ui/core/MenuItem"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faFlag } from "@fortawesome/free-regular-svg-icons"; @@ -20,12 +19,8 @@ import { saveRequestDetails } from "../../../apiManager/services/FOI/foiRequestS import { toast } from "react-toastify"; import { useDispatch } from "react-redux"; import { - restrictRequest, fetchFOIRequestDetailsWrapper, } from "../../../apiManager/services/FOI/foiRequestServices"; -import { request } from "http"; -import { is } from "immutable"; -import { setFOIUpdateLoader } from "../../../actions/FOI/foiRequestActions"; //Types are: //oipcreview @@ -41,8 +36,6 @@ const RequestFlag = ({ isActive, type, requestDetails }) => { const dispatch = useDispatch(); - - // These need to be set for each type let options; let id; @@ -53,9 +46,6 @@ const RequestFlag = ({ isActive, type, requestDetails }) => { let modalDescriptionActive = ""; let modalDescriptionInactive = ""; - let handleSaveForActive = () => {}; - let handleSaveForInactive = () => {}; - // css let iconClass; let isSelectedBgClass; @@ -245,7 +235,6 @@ const RequestFlag = ({ isActive, type, requestDetails }) => { select value={isSelected} onChange={handleValueChange} - // onClick={handleValueChange} inputProps={{ "aria-labelledby": "restrict-dropdown-label" }} input={} disabled={false} From c55a12a47b7f11b3661cf76ffb3350dabc296267 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Mon, 27 Nov 2023 11:33:17 -0800 Subject: [PATCH 039/238] Outcome validation WIP --- .../FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 7 +- .../FOIRequest/OIPCDetails/OutcomeModal.jsx | 64 +++++++++++++++++++ .../OIPCDetails/RemoveOIPCModal.jsx | 8 +-- 3 files changed, 73 insertions(+), 6 deletions(-) create mode 100644 forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OutcomeModal.jsx diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index 27cd1aac1..c02cb76a7 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -3,6 +3,7 @@ import { useState, useEffect } from "react"; import { formatDate } from "../../../../helper/FOI/helper"; import { useSelector } from "react-redux"; import RemoveOIPCModal from './RemoveOIPCModal'; +import OutcomeModal from './OutcomeModal'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faTrash } from '@fortawesome/free-solid-svg-icons'; @@ -18,6 +19,7 @@ const OIPCItem = (props) => { //Local State const [oipc, setOipc] = useState(oipcObj); const [showDeleteModal, setShowDeleteModal] = useState(false); + const [showOutcomeModal, setShowOutcomeModal] = useState(false); //Functions const generateNamesFromOIPCId = (oipcObj) => { @@ -89,7 +91,7 @@ const OIPCItem = (props) => { const newOIPCObj = oipc; newOIPCObj.outcomeid = value; setOipc(newOIPCObj); - updateOIPC(newOIPCObj); + setShowOutcomeModal(true); } const handleInquiry = (value) => { const newOIPCObj = oipc; @@ -145,7 +147,8 @@ const OIPCItem = (props) => {
- {showDeleteModal && } + {showDeleteModal && } + {showOutcomeModal && } { + + const handleSave = () => { + setShowModal(false); + updateOIPC(oipc); + }; + const handleClose = () => { + setShowModal(false); + setOipc(prev => ({ ...prev, outcomeid: null })); + }; + + return ( +
+ + +

Remove OIPC

+ + Close + + +
+ + + + Are you sure you are ready to select an outcome? This will complete the review and lock all fields + + + + + + + +
+
+ ); +}; + +export default OutcomeModal; \ No newline at end of file diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/RemoveOIPCModal.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/RemoveOIPCModal.jsx index a63c8f1ae..853c28b54 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/RemoveOIPCModal.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/RemoveOIPCModal.jsx @@ -9,16 +9,16 @@ import IconButton from '@material-ui/core/IconButton'; const RemoveOIPCModal= ({ showModal, removeOIPC, - setShowDeleteModal, + setShowModal, oipcid, }) =>{ const handleSave = () => { - setShowDeleteModal(false); + setShowModal(false); removeOIPC(oipcid) }; const handleClose = () => { - setShowDeleteModal(false); + setShowModal(false); }; return ( @@ -26,7 +26,7 @@ const RemoveOIPCModal= ({ From c5fd5906ce20a4616528a05ab832ed34d1dc34bc Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Mon, 27 Nov 2023 11:35:28 -0800 Subject: [PATCH 040/238] Add RequestFlag component to FOIRequest --- .../src/components/FOI/FOIRequest/FOIRequest.js | 7 ++++++- .../FOI/FOIRequest/FOIRequestHeader/index.js | 11 +++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index 7132275fe..3bf0747c9 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -258,7 +258,7 @@ const FOIRequest = React.memo(({ userDetail }) => { const [redactedSections, setRedactedSections] = useState(""); const [isMCFPersonal, setIsMCFPersonal] = useState(bcgovcode.replaceAll('"', '') == "MCF" && requestDetails.requestType == FOI_COMPONENT_CONSTANTS.REQUEST_TYPE_PERSONAL); const {oipcData, addOIPC, removeOIPC, updateOIPC} = useOIPCHook(); - const [showOIPCDetails, setShowOIPCDetails] = useState(true); + const [showOIPCDetails, setShowOIPCDetails] = useState(requestDetails.isoipcreview); useEffect(() => { if (window.location.href.indexOf("comments") > -1) { @@ -338,6 +338,11 @@ const FOIRequest = React.memo(({ userDetail }) => { setIsMCFPersonal(true); } } + if(requestDetails.isoipcreview) { + setShowOIPCDetails(true); + } else { + setShowOIPCDetails(false); + } }, [requestDetails]); useEffect(() => { diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js index 4ce2c617b..eaa1a1cf8 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js @@ -22,6 +22,7 @@ import { toast } from "react-toastify"; import _ from 'lodash'; import RequestRestriction from "../../customComponents/RequestRestriction"; import ConfirmModal from "../../customComponents/ConfirmModal"; +import RequestFlag from '../../customComponents/RequestFlag'; const useStyles = makeStyles((theme) => ({ formControl: { @@ -273,6 +274,16 @@ const FOIRequestHeader = React.memo( isIAORestrictedRequest={isIAORestrictedRequest} setIsLoaded={setIsLoaded} /> + +
)} {!isAddRequest && status.toLowerCase() !== StateEnum.unopened.name.toLowerCase() && (isIAORestrictedFileManager() || From d34aa81d20b53ce0ba7a24d494efa91ff0e32059 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Mon, 27 Nov 2023 14:04:17 -0800 Subject: [PATCH 041/238] outocme validation work completed. Testing wip --- .../components/FOI/FOIRequest/FOIRequest.js | 2 +- .../FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 38 ++++-- .../FOIRequest/OIPCDetails/OutcomeModal.jsx | 115 ++++++++++++------ 3 files changed, 111 insertions(+), 44 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index cf024584b..0428b841b 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -1222,7 +1222,7 @@ const FOIRequest = React.memo(({ userDetail }) => { divisions={requestDetails.divisions} /> )} - {showOIPCDetails && requestDetails.isoipcreview && requestState && requestState.toLowerCase() !== StateEnum.intakeinprogress.name.toLowerCase() && ( + {showOIPCDetails && requestState && requestState.toLowerCase() !== StateEnum.intakeinprogress.name.toLowerCase() && ( { value={oipc.oipcno} onChange = {(event) => handleOIPCNumber(event.target.value)} InputLabelProps={{ shrink: true }} - error={oipc.oipcno === ""} + error={(!oipc.outcomeid || oipc.outcomeid === 5) && oipc.oipcno === ""} required + disabled={oipc.outcomeid && oipc.outcomeid !== 5} /> @@ -172,8 +173,9 @@ const OIPCItem = (props) => { InputLabelProps={{ shrink: true }} InputProps={{inputProps: { max: formatDate(new Date())} }} type="date" - error={oipc.receiveddate === null} + error={(!oipc.outcomeid || oipc.outcomeid === 5) && oipc.receiveddate === null} required + disabled={oipc.outcomeid && oipc.outcomeid !== 5} /> @@ -185,8 +187,9 @@ const OIPCItem = (props) => { value={oipc.reviewtypeid} label="Review Type" onChange={(event) => handleReviewType(event.target.value)} - error={oipc.reviewtypeid === null} + error={(!oipc.outcomeid || oipc.outcomeid === 5) && oipc.reviewtypeid === null} required + disabled={oipc.outcomeid && oipc.outcomeid !== 5} > {uniqueReviewTypes(oipcReviewtypes).map((reviewtype) => { return {reviewtype.type_name} @@ -202,8 +205,9 @@ const OIPCItem = (props) => { value={oipc.reasonid} label="Reason" onChange = {(event) => handleReason(event.target.value)} - error={oipc.reasonid === null} + error={(!oipc.outcomeid || oipc.outcomeid === 5) && oipc.reasonid === null} required + disabled={oipc.outcomeid && oipc.outcomeid !== 5} > {oipc.reviewtypeid ? oipcReviewtypes.map((reviewtype) => { @@ -222,8 +226,9 @@ const OIPCItem = (props) => { value={oipc.statusid} label="Status" onChange = {(event) => handleStatus(event.target.value)} - error={oipc.statusid === null} + error={(!oipc.outcomeid || oipc.outcomeid === 5) && oipc.statusid === null} required + disabled={oipc.outcomeid && oipc.outcomeid !== 5} > {oipcStatuses.map((status) => { return {status.name} @@ -238,6 +243,7 @@ const OIPCItem = (props) => { onChange = {(event) => handleInvestiagtor(event.target.value)} value={oipc.investigator} InputLabelProps={{ shrink: true }} + disabled={oipc.outcomeid && oipc.outcomeid !== 5} /> @@ -251,7 +257,11 @@ const OIPCItem = (props) => { label="Outcome" > {oipcOutcomes.map((outcome) => { - return {outcome.name} + if (outcome.outcomeid !== 5) { + return {outcome.name} + } else { + return {outcome.name} + } })} @@ -265,6 +275,7 @@ const OIPCItem = (props) => { InputLabelProps={{ shrink: true }} InputProps={{inputProps: { max: formatDate(new Date())} }} type="date" + disabled={oipc.outcomeid && oipc.outcomeid !== 5} /> @@ -274,12 +285,14 @@ const OIPCItem = (props) => { handleInquiry(true)} + disabled={oipc.outcomeid && oipc.outcomeid !== 5} />} label="Yes" /> handleInquiry(false)} + disabled={oipc.outcomeid && oipc.outcomeid !== 5} />} label="No" /> @@ -289,12 +302,14 @@ const OIPCItem = (props) => { handleJudicalReview(true)} + disabled={oipc.outcomeid && oipc.outcomeid !== 5} />} label="Yes" /> handleJudicalReview(false)} + disabled={oipc.outcomeid && oipc.outcomeid !== 5} />} label="No" /> @@ -304,12 +319,14 @@ const OIPCItem = (props) => { handleSubsequentAppeal(true)} + disabled={oipc.outcomeid && oipc.outcomeid !== 5} />} label="Yes" /> handleSubsequentAppeal(false)} + disabled={oipc.outcomeid && oipc.outcomeid !== 5} />} label="No" /> @@ -327,8 +344,9 @@ const OIPCItem = (props) => { InputLabelProps={{ shrink: true }} InputProps={{inputProps: { min: oipc.receiveddate ? formatDate(new Date(oipc.receiveddate)) : null } }} type="date" - error={oipc.inquiryattributes.inquirydate === null} + error={(!oipc.outcomeid || oipc.outcomeid === 5) && oipc.inquiryattributes.inquirydate === null} required + disabled={oipc.outcomeid && oipc.outcomeid !== 5} /> @@ -339,8 +357,9 @@ const OIPCItem = (props) => { value={oipc.inquiryattributes.orderno} onChange = {(event) => handleInquiryFields(event.target.value, "ORDERNO")} InputLabelProps={{ shrink: true }} - error={oipc.inquiryattributes.orderno === ""} + error={(!oipc.outcomeid || oipc.outcomeid === 5) && oipc.inquiryattributes.orderno === ""} required + disabled={oipc.outcomeid && oipc.outcomeid !== 5} /> @@ -352,8 +371,9 @@ const OIPCItem = (props) => { fullWidth value={oipc.inquiryattributes.inquiryoutcome} label="Outcome" - error={oipc.inquiryattributes.inquiryoutcome === null} + error={(!oipc.outcomeid || oipc.outcomeid === 5) && oipc.inquiryattributes.inquiryoutcome === null} required + disabled={oipc.outcomeid && oipc.outcomeid !== 5} > {oipcInquiryoutcomes.map((inquiryoutcome) => { return {inquiryoutcome.name} diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OutcomeModal.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OutcomeModal.jsx index 7f49f26c0..b1426c52a 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OutcomeModal.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OutcomeModal.jsx @@ -22,42 +22,89 @@ const OutcomeModal= ({ setShowModal(false); setOipc(prev => ({ ...prev, outcomeid: null })); }; + const handleAmendSave = () => { + setShowModal(false); + setOipc(prev => ({ ...prev, outcomeid: null })); + updateOIPC(oipc); + } + const handleAmendClose = () => { + setShowModal(false); + } - return ( -
- - -

Remove OIPC

- - Close - - -
- - - - Are you sure you are ready to select an outcome? This will complete the review and lock all fields - - - - - + + +
+
+ : +
+ - Continue - - - - -
+ +

Close OIPC

+ + Close + + +
+ + + + Are you sure you are ready to select an outcome? This will complete the review and lock all fields + + + + + + + + + + } + ); }; From c37f11ef0387ffdd86db1d94377a5e6d534c0ed7 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Mon, 27 Nov 2023 14:31:50 -0800 Subject: [PATCH 042/238] Adjustments to fe disabling of outcomes --- .../src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index b4d3fd4a9..45f26fb87 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -260,7 +260,7 @@ const OIPCItem = (props) => { if (outcome.outcomeid !== 5) { return {outcome.name} } else { - return {outcome.name} + return {outcome.name} } })} From 0df84fe770e6fff49b78c1b6fb8bf4cb2698da10 Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Mon, 27 Nov 2023 15:21:30 -0800 Subject: [PATCH 043/238] Redo layout to incorporate request flags --- .../MinistryReview/RequestHeader.js | 28 +++++++++++++++---- .../customComponents/requestrestriction.scss | 2 -- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/RequestHeader.js b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/RequestHeader.js index 7d0bd79d0..44e0eaafd 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/RequestHeader.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/RequestHeader.js @@ -13,6 +13,7 @@ import { isRequestWatcherOrMinistryAssignee, addToRestrictedRequestTagList } fro import RequestMinistryRestriction from "../../customComponents/RequestMinistryRestriction"; import _ from 'lodash'; import {setCommentTagListLoader} from "../../../../actions/FOI/foiRequestActions"; +import RequestFlag from '../../customComponents/RequestFlag'; const RequestHeader = React.memo(({ requestDetails, @@ -101,6 +102,20 @@ const RequestHeader = React.memo(({ ) ); + const requestFlagsBox = ( +
+ + +
+ ); return ( <>
@@ -128,12 +143,9 @@ const RequestHeader = React.memo(({
-
-
-
+
{watcherBox} -
- { + { (isLoaded && (isRequestWatcherOrMinistryAssignee(requestWatchers,ministryAssigneeValue,userDetail?.preferred_username) || isMinistryRestrictedFileManager())) && } +
+
+
+ {requestFlagsBox}
-
+
Date: Mon, 27 Nov 2023 16:21:31 -0800 Subject: [PATCH 044/238] All validation work completed. WIP Testing + refactor + restyling --- .../FOI/FOIRequest/OIPCDetails/AmendModal.jsx | 66 ++++++++++ .../FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 6 + .../FOIRequest/OIPCDetails/OutcomeModal.jsx | 115 ++++++------------ 3 files changed, 106 insertions(+), 81 deletions(-) create mode 100644 forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/AmendModal.jsx diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/AmendModal.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/AmendModal.jsx new file mode 100644 index 000000000..1554df284 --- /dev/null +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/AmendModal.jsx @@ -0,0 +1,66 @@ +import Dialog from '@material-ui/core/Dialog'; +import DialogActions from '@material-ui/core/DialogActions'; +import DialogContent from '@material-ui/core/DialogContent'; +import DialogContentText from '@material-ui/core/DialogContentText'; +import DialogTitle from '@material-ui/core/DialogTitle'; +import CloseIcon from '@material-ui/icons/Close'; +import IconButton from '@material-ui/core/IconButton'; + +const AmendModal= ({ + showModal, + setShowModal, + updateOIPC, + oipc, + setOipc, +}) =>{ + + const handleSave = () => { + setShowModal(false); + const newOIPCObj = oipc; + newOIPCObj.outcomeid = null; + setOipc(newOIPCObj); + updateOIPC(newOIPCObj); + }; + const handleClose = () => { + setShowModal(false); + }; + + return ( +
+ + +

Amend Outcome

+ + Close + + +
+ + + + Are you sure you want to amend this completed OIPC review? You will need to re-select an outcome to close it again. + + + + + + + +
+
+ ); +}; + +export default AmendModal; \ No newline at end of file diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index 45f26fb87..142962fe1 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -4,6 +4,7 @@ import { formatDate } from "../../../../helper/FOI/helper"; import { useSelector } from "react-redux"; import RemoveOIPCModal from './RemoveOIPCModal'; import OutcomeModal from './OutcomeModal'; +import AmendModal from './AmendModal'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faTrash } from '@fortawesome/free-solid-svg-icons'; @@ -20,6 +21,7 @@ const OIPCItem = (props) => { const [oipc, setOipc] = useState(oipcObj); const [showDeleteModal, setShowDeleteModal] = useState(false); const [showOutcomeModal, setShowOutcomeModal] = useState(false); + const [showAmendModal, setShowAmendModal] = useState(false); //Functions const generateNamesFromOIPCId = (oipcObj) => { @@ -88,6 +90,9 @@ const OIPCItem = (props) => { updateOIPC(newOIPCObj); } const handleOutcome = (value) => { + if (value === 5) { + return setShowAmendModal(true); + } const newOIPCObj = oipc; newOIPCObj.outcomeid = value; setOipc(newOIPCObj); @@ -149,6 +154,7 @@ const OIPCItem = (props) => {
{showDeleteModal && } {showOutcomeModal && } + {showAmendModal && } ({ ...prev, outcomeid: null })); }; - const handleAmendSave = () => { - setShowModal(false); - setOipc(prev => ({ ...prev, outcomeid: null })); - updateOIPC(oipc); - } - const handleAmendClose = () => { - setShowModal(false); - } - + return ( - <> - {oipc.outcomeid === 5 ? -
- - -

Amend Outcome

- - Close - - -
- - - - Are you sure you want to amend this completed OIPC review? You will need to re-select an outcome to close it again - - - - - - - -
-
- : -
- + + +

Close OIPC

+ + Close + + +
+ + + + Are you sure you are ready to select an outcome? This will complete the review and lock all fields. + + + + + - - -
-
- } - + Continue + + + + +
); }; From fa9acac48e4b0cb572d82d444164508003e92a6c Mon Sep 17 00:00:00 2001 From: "sumathi.thirumani" Date: Tue, 28 Nov 2023 04:23:37 -0800 Subject: [PATCH 045/238] Fix for oipc outcome id issue. --- request-management-api/request_api/schemas/foirequestwrapper.py | 2 +- .../request_api/services/foirequest/requestservicegetter.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/request-management-api/request_api/schemas/foirequestwrapper.py b/request-management-api/request_api/schemas/foirequestwrapper.py index 967a67a14..4cfc64bea 100644 --- a/request-management-api/request_api/schemas/foirequestwrapper.py +++ b/request-management-api/request_api/schemas/foirequestwrapper.py @@ -72,7 +72,7 @@ class Meta: # pylint: disable=too-few-public-methods reviewtypeid = fields.Int(data_key="reviewtypeid") reasonid = fields.Int(data_key="reasonid") statusid = fields.Int(data_key="statusid") - outcomeid = fields.Int(data_key="outcomeid") + outcomeid = fields.Int(data_key="outcomeid",allow_none=True) investigator = fields.Str(data_key="investigator",allow_none=True, validate=[validate.Length(max=500, error=MAX_EXCEPTION_MESSAGE)]) isinquiry = fields.Bool(data_key="isinquiry") isjudicialreview = fields.Bool(data_key="isjudicialreview") diff --git a/request-management-api/request_api/services/foirequest/requestservicegetter.py b/request-management-api/request_api/services/foirequest/requestservicegetter.py index 1e9c371da..78181e224 100644 --- a/request-management-api/request_api/services/foirequest/requestservicegetter.py +++ b/request-management-api/request_api/services/foirequest/requestservicegetter.py @@ -228,7 +228,7 @@ def getoipcdetails(self, ministryrequestid, ministryrequestversion): "statusid": entry["statusid"], "status":entry["status.name"], "outcomeid": entry["outcomeid"], - "outcome": entry["outcome.name"], + "outcome": entry["outcome.name"] if entry["outcomeid"] not in (None, '') else None, "investigator": entry["investigator"], "isinquiry": entry["isinquiry"], "isjudicialreview": entry["isjudicialreview"], From 2bc0e8a4333be537db4bdc860f8c84c326968be1 Mon Sep 17 00:00:00 2001 From: "sumathi.thirumani" Date: Tue, 28 Nov 2023 08:03:30 -0800 Subject: [PATCH 046/238] closedate exclude blank value --- .../services/foirequest/requestservicebuilder.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/request-management-api/request_api/services/foirequest/requestservicebuilder.py b/request-management-api/request_api/services/foirequest/requestservicebuilder.py index 1e89300e4..b6315671b 100644 --- a/request-management-api/request_api/services/foirequest/requestservicebuilder.py +++ b/request-management-api/request_api/services/foirequest/requestservicebuilder.py @@ -144,13 +144,13 @@ def prepareoipc(self, requestschema, ministryrequestid, version, userid): oipcreview.reasonid = oipc["reasonid"] oipcreview.statusid = oipc["statusid"] oipcreview.outcomeid = oipc["outcomeid"] - oipcreview.investigator = oipc["investigator"] + oipcreview.investigator = oipc["investigator"] if oipc["investigator"] not in (None, "") else None oipcreview.isinquiry = oipc["isinquiry"] oipcreview.isjudicialreview = oipc["isjudicialreview"] oipcreview.issubsequentappeal = oipc["issubsequentappeal"] oipcreview.issubsequentappeal = oipc["issubsequentappeal"] - oipcreview.receiveddate = oipc["receiveddate"] - oipcreview.closeddate = oipc["closeddate"] + oipcreview.receiveddate = oipc["receiveddate"] if oipc["receiveddate"] not in (None, "") else None + oipcreview.closeddate = oipc["closeddate"] if oipc["closeddate"] not in (None, "") else None oipcreview.isactive = True if oipc["isinquiry"] == True: oipcreview.inquiryattributes = oipc["inquiryattributes"] From 87042f52b520baac60075410eb51f106133b2497 Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Tue, 28 Nov 2023 09:13:52 -0800 Subject: [PATCH 047/238] Update layout for RequestFlags --- .../FOI/FOIRequest/FOIRequestHeader/index.js | 30 +++++++++---------- .../MinistryReview/RequestHeader.js | 16 +++++----- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js index eaa1a1cf8..74da8994b 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js @@ -260,11 +260,9 @@ const FOIRequestHeader = React.memo(
-
-
+
{window.location.href.indexOf(FOI_COMPONENT_CONSTANTS.ADDREQUEST) === -1 && ( -
- - -
)} {!isAddRequest && status.toLowerCase() !== StateEnum.unopened.name.toLowerCase() && (isIAORestrictedFileManager() || (isLoaded && isRequestWatcherOrAssignee(requestWatchers,assigneeObj,userDetail?.preferred_username))) && @@ -294,9 +281,20 @@ const FOIRequestHeader = React.memo( requestDetails={requestDetails} /> } -
-
+
+ + +
+
{showMinistryAssignedTo && ( <> diff --git a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/RequestHeader.js b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/RequestHeader.js index 44e0eaafd..4071f16fe 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/RequestHeader.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/RequestHeader.js @@ -144,16 +144,16 @@ const RequestHeader = React.memo(({
- {watcherBox} - { + {watcherBox} + { (isLoaded && (isRequestWatcherOrMinistryAssignee(requestWatchers,ministryAssigneeValue,userDetail?.preferred_username) || isMinistryRestrictedFileManager())) && - - } + + }
From a8be867f658fcd87efe943067ae43bcb25ab7bbb Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Tue, 28 Nov 2023 09:21:13 -0800 Subject: [PATCH 048/238] Small code change to oipc object --- .../src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index 142962fe1..e7bec8f3b 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -33,10 +33,10 @@ const OIPCItem = (props) => { return {...prev, reviewtypeName: reviewtype ? reviewtype.type_name : ""} }) setOipc((prev) => { - return {...prev, statusName: status ? status.type_name : ""} + return {...prev, statusName: status ? status.status : ""} }) setOipc((prev) => { - return {...prev, outcomeName: outcome ? outcome.type_name : ""} + return {...prev, outcomeName: outcome ? outcome.outcome : ""} }) setOipc((prev) => { return {...prev, reasonName: reviewtype ? reviewtype.reason_name : ""} From a696e89662a999d97657017836ea539b1b3e382f Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Tue, 28 Nov 2023 13:14:08 -0800 Subject: [PATCH 049/238] WIP Flag Ingtegration + code adjustments --- .../FOI/FOIRequest/BottomButtonGroup/index.js | 8 ++++++-- .../src/components/FOI/FOIRequest/FOIRequest.js | 10 ++++++++++ .../FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx | 2 +- .../components/FOI/FOIRequest/OIPCDetails/oipcHook.js | 8 +++++--- forms-flow-web/src/components/FOI/FOIRequest/utils.js | 2 +- 5 files changed, 23 insertions(+), 7 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/BottomButtonGroup/index.js b/forms-flow-web/src/components/FOI/FOIRequest/BottomButtonGroup/index.js index 1b2d06b3c..fa6a7df22 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/BottomButtonGroup/index.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/BottomButtonGroup/index.js @@ -120,9 +120,13 @@ const BottomButtonGroup = React.memo( setIsAddRequest(false); } - //add oipc Data to save request object + //add oipc Data to save request object and sync/validate isoipcreview attribute saveRequestObject.oipcdetails = oipcData; - if (oipcData.length <= 0) saveRequestObject.isoipcreview = false; + if (oipcData.length > 0) { + saveRequestObject.isoipcreview = true; + } else { + saveRequestObject.isoipcreview = false; + } dispatch(setFOILoader(setLoader)) dispatch( diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index 6dfa7961b..8a6ae0ec4 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -345,6 +345,16 @@ const FOIRequest = React.memo(({ userDetail }) => { } }, [requestDetails]); + //useEffect to manage isoipcreview attribute for requestdetails state + useEffect(() => { + if(Object.keys(requestDetails).length !== 0 && oipcData?.length <= 0) { + requestDetails.isoipcreview = false; + setShowOIPCDetails(false); + } + }, [oipcData]) + + console.log(requestDetails) + useEffect(() => { if (isIAORestricted) dispatch(fetchRestrictedRequestCommentTagList(requestId, ministryId)); diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx index afa6f2fa8..2e06dfe43 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx @@ -10,7 +10,7 @@ const OIPCDetailsList = (props) => { return ( <> - {index !== (oipcData.length - 1) && } + {index !== (oipcData?.length - 1) && } ); }); diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js index d9fb732a4..f75a4e500 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js @@ -28,8 +28,6 @@ const useOIPCHook = () => { issubsequentappeal: false, }]; } - } else { - return []; } } const [oipcData, setOipcData] = useState(requestDetails.oipcdetails); @@ -45,7 +43,7 @@ const useOIPCHook = () => { const addOIPC = () => { setOipcData((prev) => { return [...prev, { - id: oipcData.length > 0 ? oipcData[oipcData.length - 1].id + 1 : 0, + id: oipcData?.length > 0 ? oipcData[oipcData.length - 1].id + 1 : 0, oipcno: "", reviewtypeid: null, reasonid: null, @@ -79,6 +77,9 @@ const useOIPCHook = () => { }); }); } + const removeAllOIPCs = () => { + setOipcData([]); + } return { oipcData, @@ -86,6 +87,7 @@ const useOIPCHook = () => { removeOIPC, updateOIPC, stageOIPCData, + removeAllOIPCs, }; }; diff --git a/forms-flow-web/src/components/FOI/FOIRequest/utils.js b/forms-flow-web/src/components/FOI/FOIRequest/utils.js index f71148f4b..81d20752c 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/utils.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/utils.js @@ -348,7 +348,7 @@ export const checkValidationError = ( !requiredRequestDetailsValues.receivedDate || !requiredRequestDetailsValues.requestStartDate || !requiredAxisDetails.axisRequestId || - (oipcData.length > 0 && isOipcReview && oipcData.some((oipc) => { + (oipcData?.length > 0 && isOipcReview && oipcData?.some((oipc) => { return oipc.oipcno === "" || oipc.receiveddate === null || oipc.reviewtypeid === null || oipc.reasonid === null || oipc.statusid === null || oipc.inquiryattributes?.orderno === "" || oipc.inquiryattributes?.inquiryoutcome === null || oipc.inquiryattributes?.inquirydate === null; })) From 3ef75ccec853b6b9999aa36f93626fd4a2efabfa Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Tue, 28 Nov 2023 14:48:34 -0800 Subject: [PATCH 050/238] Small code changes + modal design adjustments --- .../components/FOI/FOIRequest/OIPCDetails/AmendModal.jsx | 2 +- .../src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 6 +++--- .../components/FOI/FOIRequest/OIPCDetails/OutcomeModal.jsx | 2 +- .../components/FOI/FOIRequest/OIPCDetails/oipcdetails.scss | 1 - 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/AmendModal.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/AmendModal.jsx index 1554df284..ba4912ae8 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/AmendModal.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/AmendModal.jsx @@ -42,7 +42,7 @@ const AmendModal= ({ - + Are you sure you want to amend this completed OIPC review? You will need to re-select an outcome to close it again. diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index e7bec8f3b..f0d7275fd 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -28,15 +28,15 @@ const OIPCItem = (props) => { const reviewtype = oipcReviewtypes.find(reviewtype => reviewtype.reviewtypeid === oipcObj.reviewtypeid && reviewtype.reasonid === oipcObj.reasonid); const status = oipcStatuses.find(status => status.statusid === oipcObj.statusid); const outcome = oipcOutcomes.find(outcome => outcome.outcomeid === oipcObj.outcomeid); - + setOipc((prev) => { return {...prev, reviewtypeName: reviewtype ? reviewtype.type_name : ""} }) setOipc((prev) => { - return {...prev, statusName: status ? status.status : ""} + return {...prev, statusName: status ? status.name : ""} }) setOipc((prev) => { - return {...prev, outcomeName: outcome ? outcome.outcome : ""} + return {...prev, outcomeName: outcome ? outcome.name : ""} }) setOipc((prev) => { return {...prev, reasonName: reviewtype ? reviewtype.reason_name : ""} diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OutcomeModal.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OutcomeModal.jsx index 6a7e75783..34efe936e 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OutcomeModal.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OutcomeModal.jsx @@ -40,7 +40,7 @@ const OutcomeModal= ({ - + Are you sure you are ready to select an outcome? This will complete the review and lock all fields. diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcdetails.scss b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcdetails.scss index 4683c050f..d28779da2 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcdetails.scss +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcdetails.scss @@ -1,4 +1,3 @@ - .align-division{ text-align: center; } From 639e8c0de0b8bcb77f8fefc5f57871872d49b3e7 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Tue, 28 Nov 2023 14:57:10 -0800 Subject: [PATCH 051/238] Mandatory date validation adjusted (inquiry date and received date) --- forms-flow-web/src/components/FOI/FOIRequest/utils.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/utils.js b/forms-flow-web/src/components/FOI/FOIRequest/utils.js index 81d20752c..2905bfea2 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/utils.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/utils.js @@ -349,8 +349,8 @@ export const checkValidationError = ( !requiredRequestDetailsValues.requestStartDate || !requiredAxisDetails.axisRequestId || (oipcData?.length > 0 && isOipcReview && oipcData?.some((oipc) => { - return oipc.oipcno === "" || oipc.receiveddate === null || oipc.reviewtypeid === null || oipc.reasonid === null || oipc.statusid === null || - oipc.inquiryattributes?.orderno === "" || oipc.inquiryattributes?.inquiryoutcome === null || oipc.inquiryattributes?.inquirydate === null; + return oipc.oipcno === "" || oipc.receiveddate === null || oipc.receiveddate === "" || oipc.reviewtypeid === null || oipc.reasonid === null || oipc.statusid === null || + oipc.inquiryattributes?.orderno === "" || oipc.inquiryattributes?.inquiryoutcome === null || oipc.inquiryattributes?.inquirydate === null || oipc.inquiryattributes?.inquirydate === ""; })) ); }; From 1343ece01d0db727113290cf1387085fbd37c07d Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Tue, 28 Nov 2023 15:31:18 -0800 Subject: [PATCH 052/238] Save request in raw request state bug fix --- .../src/components/FOI/FOIRequest/BottomButtonGroup/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/BottomButtonGroup/index.js b/forms-flow-web/src/components/FOI/FOIRequest/BottomButtonGroup/index.js index fa6a7df22..458fc2147 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/BottomButtonGroup/index.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/BottomButtonGroup/index.js @@ -122,7 +122,7 @@ const BottomButtonGroup = React.memo( //add oipc Data to save request object and sync/validate isoipcreview attribute saveRequestObject.oipcdetails = oipcData; - if (oipcData.length > 0) { + if (oipcData?.length > 0) { saveRequestObject.isoipcreview = true; } else { saveRequestObject.isoipcreview = false; From bcb35a01ae9b2780f0623c4c17b435af2377b31e Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Tue, 28 Nov 2023 15:53:39 -0800 Subject: [PATCH 053/238] Add column to getbasequery --- .../request_api/models/FOIMinistryRequests.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index 7f203d8d0..8abc19dc7 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -1010,7 +1010,8 @@ def getbasequery(cls, iaoassignee, ministryassignee, userid=None, requestby='IAO extensions, FOIRestrictedMinistryRequest.isrestricted.label('isiaorestricted'), ministry_restricted_requests.isrestricted.label('isministryrestricted'), - SubjectCode.name.label('subjectcode') + SubjectCode.name.label('subjectcode'), + FOIMinistryRequest.isoipcreview.label('isoipcreview') ] basequery = _session.query( From 0e54fb987baa0570bd8a97777f58605a7239badd Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Tue, 28 Nov 2023 15:59:30 -0800 Subject: [PATCH 054/238] Update request flag --- .../components/FOI/FOIRequest/FOIRequest.js | 17 ++++- .../FOI/FOIRequest/FOIRequestHeader/index.js | 5 ++ .../FOI/customComponents/RequestFlag.js | 71 +++---------------- 3 files changed, 30 insertions(+), 63 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index 8a6ae0ec4..665bd3f53 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -258,7 +258,7 @@ const FOIRequest = React.memo(({ userDetail }) => { const [redactedSections, setRedactedSections] = useState(""); const [isMCFPersonal, setIsMCFPersonal] = useState(bcgovcode.replaceAll('"', '') == "MCF" && requestDetails.requestType == FOI_COMPONENT_CONSTANTS.REQUEST_TYPE_PERSONAL); const {oipcData, addOIPC, removeOIPC, updateOIPC} = useOIPCHook(); - const [showOIPCDetails, setShowOIPCDetails] = useState(requestDetails.isoipcreview); + const [showOIPCDetails, setShowOIPCDetails] = useState(requestDetails.oipcData?.length > 0); useEffect(() => { if (window.location.href.indexOf("comments") > -1) { @@ -649,6 +649,18 @@ const FOIRequest = React.memo(({ userDetail }) => { setAssignedToValue(value); }; + const oipcSectionRef = React.useRef(null); + const handleOipcReviewFlagChange = (isSelected) => { + setShowOIPCDetails(isSelected); + oipcSectionRef.current.scrollIntoView(); + //timeout to allow react state to update after setState call + if (isSelected) { + setTimeout(() => { + oipcSectionRef.current.scrollIntoView(); + }, (10)); + } + } + //handle email validation const [validation, setValidation] = React.useState({}); const handleEmailValidation = (validationObj) => { @@ -1122,6 +1134,8 @@ const FOIRequest = React.memo(({ userDetail }) => { userDetail={userDetail} disableInput={disableInput} isAddRequest={isAddRequest} + handleOipcReviewFlagChange={handleOipcReviewFlagChange} + showOipcReviewFlag={requestState.toLowerCase() !== StateEnum.intakeinprogress.name.toLowerCase()} /> {(isAddRequest || requestState === StateEnum.unopened.name) && ( @@ -1237,6 +1251,7 @@ const FOIRequest = React.memo(({ userDetail }) => { divisions={requestDetails.divisions} /> )} +
{showOIPCDetails && requestState && requestState.toLowerCase() !== StateEnum.intakeinprogress.name.toLowerCase() && ( { /** * Header of Review request in the UI @@ -287,11 +289,14 @@ const FOIRequestHeader = React.memo( type="oipcreview" requestDetails={requestDetails} isActive={requestDetails.isoipcreview} + handleSelect={handleOipcReviewFlagChange} + showFlag={showOipcReviewFlag} />
diff --git a/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js b/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js index abfc21310..1109fe8b4 100644 --- a/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js +++ b/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js @@ -1,6 +1,5 @@ import { useState } from "react"; import "./requestflag.scss"; - import OutlinedInput from "@material-ui/core/OutlinedInput"; import MenuItem from "@material-ui/core/MenuItem"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; @@ -15,17 +14,12 @@ import CloseIcon from "@material-ui/icons/Close"; import IconButton from "@material-ui/core/IconButton"; import TextField from "@mui/material/TextField"; import { useParams } from "react-router-dom"; -import { saveRequestDetails } from "../../../apiManager/services/FOI/foiRequestServices"; -import { toast } from "react-toastify"; import { useDispatch } from "react-redux"; -import { - fetchFOIRequestDetailsWrapper, -} from "../../../apiManager/services/FOI/foiRequestServices"; //Types are: //oipcreview //phasedrelease -const RequestFlag = ({ isActive, type, requestDetails }) => { +const RequestFlag = ({ isActive, type, handleSelect, showFlag = true }) => { const [isSelected, setIsSelected] = useState(isActive || false); const [modalOpen, setModalOpen] = useState(false); const [modalHeading, setModalHeading] = useState(""); @@ -133,7 +127,12 @@ const RequestFlag = ({ isActive, type, requestDetails }) => { } const handleValueChange = (e) => { - setModalOpen(true); + setIsSelected(e.target.value); + if (type == "oipcreview" && !isActive) { + handleSelect(e.target.value) + } else { + setModalOpen(true); + } if (e.target.value == true) { setModalHeading(modalHeadingActive); @@ -144,7 +143,6 @@ const RequestFlag = ({ isActive, type, requestDetails }) => { setModalMessage(modalMessageInactive); setModalDescription(modalDescriptionInactive); } - setIsSelected(e.target.value); }; const handleClose = () => { @@ -154,61 +152,10 @@ const RequestFlag = ({ isActive, type, requestDetails }) => { const handleSave = (e) => { setModalOpen(false); - saveOipcReviewStatus(); - }; - - const saveOipcReviewStatus = () => { - let updatedRequestDetails; - if (type == "oipcreview") { - updatedRequestDetails = { - ...requestDetails, - isoipcreview: isSelected, - }; - } else if (type == "phasedrelease") { - updatedRequestDetails = { - ...requestDetails, - isphasedrelease: isSelected, - }; - } - //dispatch loader - dispatch( - saveRequestDetails( - updatedRequestDetails, - -2, //not an add request - requestId, - ministryId, - (err, res) => { - if (!err) { - toast.success("The OIPC review status has been successfully updated.", { - position: "top-right", - autoClose: 3000, - hideProgressBar: true, - closeOnClick: true, - pauseOnHover: true, - draggable: true, - progress: undefined, - }); - dispatch(fetchFOIRequestDetailsWrapper(requestId, ministryId)); - } else { - toast.error( - "Temporarily unable to update the OIPC review status. Please try again in a few minutes.", - { - position: "top-right", - autoClose: 3000, - hideProgressBar: true, - closeOnClick: true, - pauseOnHover: true, - draggable: true, - progress: undefined, - } - ); - setIsSelected(isActive || false); - } - } - ) - ); + handleSelect(isSelected); }; + if (!showFlag) return <>; return ( <>
From 80fa9dab01aabfc14107c110d348d0b9b0fb0ccc Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Tue, 28 Nov 2023 16:00:06 -0800 Subject: [PATCH 055/238] Add RequestFlag to Ministry view --- .../MinistryReview/MinistryReview.js | 26 +++++++++++++++++++ .../MinistryReview/RequestHeader.js | 5 +++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js index 6b779db48..4071f7ae0 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js @@ -62,6 +62,8 @@ import { UnsavedModal } from "../../customComponents"; import { DISABLE_GATHERINGRECORDS_TAB } from "../../../../constants/constants"; import _ from "lodash"; import { MinistryNeedsScanning } from "../../../../constants/FOI/enum"; +import OIPCDetails from "../OIPCDetails/Index"; +import useOIPCHook from "../OIPCDetails/oipcHook"; const useStyles = makeStyles((theme) => ({ root: { @@ -108,6 +110,8 @@ const MinistryReview = React.memo(({ userDetail }) => { const [_currentrequestStatus, setcurrentrequestStatus] = React.useState(""); const [_tabStatus, settabStatus] = React.useState(requestState); + const {oipcData, addOIPC, removeOIPC, updateOIPC} = useOIPCHook(); + const [showOIPCDetails, setShowOIPCDetails] = useState(requestDetails.oipcData?.length > 0); //gets the request detail from the store const IsDivisionalCoordinator = () => { return userDetail?.role?.includes("DivisionalCoordinator"); @@ -582,6 +586,18 @@ const MinistryReview = React.memo(({ userDetail }) => { (state) => state.foiRequests.showEventQueue ); + const oipcSectionRef = React.useRef(null); + const handleOipcReviewFlagChange = (isSelected) => { + setShowOIPCDetails(isSelected); + oipcSectionRef.current.scrollIntoView(); + //timeout to allow react state to update after setState call + if (isSelected) { + setTimeout(() => { + oipcSectionRef.current.scrollIntoView(); + }, (10)); + } + } + return !isLoading && requestDetails && Object.keys(requestDetails).length !== 0 && @@ -752,6 +768,7 @@ const MinistryReview = React.memo(({ userDetail }) => { setSaveMinistryRequestObject } ministryAssigneeValue={ministryAssignedToValue} + handleOipcReviewFlagChange={handleOipcReviewFlagChange} /> @@ -767,6 +784,15 @@ const MinistryReview = React.memo(({ userDetail }) => { /> {divisionsBox} {/* */} +
+ {showOIPCDetails && requestState && requestState.toLowerCase() !== StateEnum.intakeinprogress.name.toLowerCase() && ( + + )} { const { requestId, ministryId } = useParams(); const _requestDetails = requestDetails; @@ -108,11 +109,13 @@ const RequestHeader = React.memo(({ type="oipcreview" requestDetails={requestDetails} isActive={requestDetails.isoipcreview} + handleSelect={handleOipcReviewFlagChange} /> console.log('selected')} />
); From cbc0f223b14f8ad74906bc2b8ceb67edfcff3949 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Tue, 28 Nov 2023 16:00:19 -0800 Subject: [PATCH 056/238] Saving bug for raw requests fixed --- .../FOI/FOIRequest/BottomButtonGroup/index.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/BottomButtonGroup/index.js b/forms-flow-web/src/components/FOI/FOIRequest/BottomButtonGroup/index.js index 458fc2147..cad544815 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/BottomButtonGroup/index.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/BottomButtonGroup/index.js @@ -121,11 +121,13 @@ const BottomButtonGroup = React.memo( } //add oipc Data to save request object and sync/validate isoipcreview attribute - saveRequestObject.oipcdetails = oipcData; - if (oipcData?.length > 0) { - saveRequestObject.isoipcreview = true; - } else { - saveRequestObject.isoipcreview = false; + if (requestState.toLowerCase() !== StateEnum.intakeinprogress.name.toLowerCase() && requestState.toLowerCase() !== StateEnum.unopened.name.toLowerCase()) { + saveRequestObject.oipcdetails = oipcData; + // if (oipcData?.length > 0) { + // saveRequestObject.isoipcreview = true; + // } else { + // saveRequestObject.isoipcreview = false; + // } } dispatch(setFOILoader(setLoader)) From 7b0755efae49340d68a56c94c21721e0fbdf75c6 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Tue, 28 Nov 2023 16:04:40 -0800 Subject: [PATCH 057/238] design changes --- .../src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index f0d7275fd..483518590 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -167,6 +167,7 @@ const OIPCItem = (props) => { error={(!oipc.outcomeid || oipc.outcomeid === 5) && oipc.oipcno === ""} required disabled={oipc.outcomeid && oipc.outcomeid !== 5} + placeholder="OIPC Number" /> @@ -250,6 +251,7 @@ const OIPCItem = (props) => { value={oipc.investigator} InputLabelProps={{ shrink: true }} disabled={oipc.outcomeid && oipc.outcomeid !== 5} + placeholder="Firstname Lastname" /> @@ -366,6 +368,7 @@ const OIPCItem = (props) => { error={(!oipc.outcomeid || oipc.outcomeid === 5) && oipc.inquiryattributes.orderno === ""} required disabled={oipc.outcomeid && oipc.outcomeid !== 5} + placeholder="Order Number" /> @@ -380,7 +383,7 @@ const OIPCItem = (props) => { error={(!oipc.outcomeid || oipc.outcomeid === 5) && oipc.inquiryattributes.inquiryoutcome === null} required disabled={oipc.outcomeid && oipc.outcomeid !== 5} - > + > {oipcInquiryoutcomes.map((inquiryoutcome) => { return {inquiryoutcome.name} })} From 7c8bc271cd6f4b8e503c4c5a3036c3a77074d47f Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Tue, 28 Nov 2023 19:00:28 -0800 Subject: [PATCH 058/238] Adjusted flag button to change request details isoipcreview attribute + adjusted state to manage displaying the oipc details section --- .../FOI/FOIRequest/BottomButtonGroup/index.js | 2 +- .../src/components/FOI/FOIRequest/FOIRequest.js | 16 ++++++++-------- .../FOIRequest/MinistryReview/MinistryReview.js | 9 +++++---- .../FOI/FOIRequest/OIPCDetails/oipcHook.js | 8 ++++++-- 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/BottomButtonGroup/index.js b/forms-flow-web/src/components/FOI/FOIRequest/BottomButtonGroup/index.js index cad544815..7a9e7c217 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/BottomButtonGroup/index.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/BottomButtonGroup/index.js @@ -122,7 +122,7 @@ const BottomButtonGroup = React.memo( //add oipc Data to save request object and sync/validate isoipcreview attribute if (requestState.toLowerCase() !== StateEnum.intakeinprogress.name.toLowerCase() && requestState.toLowerCase() !== StateEnum.unopened.name.toLowerCase()) { - saveRequestObject.oipcdetails = oipcData; + saveRequestObject.oipcdetails = oipcData ? oipcData : []; // if (oipcData?.length > 0) { // saveRequestObject.isoipcreview = true; // } else { diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index 665bd3f53..7532dd07f 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -257,8 +257,7 @@ const FOIRequest = React.memo(({ userDetail }) => { const [isIAORestricted, setIsIAORestricted] = useState(false); const [redactedSections, setRedactedSections] = useState(""); const [isMCFPersonal, setIsMCFPersonal] = useState(bcgovcode.replaceAll('"', '') == "MCF" && requestDetails.requestType == FOI_COMPONENT_CONSTANTS.REQUEST_TYPE_PERSONAL); - const {oipcData, addOIPC, removeOIPC, updateOIPC} = useOIPCHook(); - const [showOIPCDetails, setShowOIPCDetails] = useState(requestDetails.oipcData?.length > 0); + const {oipcData, addOIPC, removeOIPC, updateOIPC, isOIPCReview, setIsOIPCReview} = useOIPCHook(); useEffect(() => { if (window.location.href.indexOf("comments") > -1) { @@ -339,9 +338,9 @@ const FOIRequest = React.memo(({ userDetail }) => { } } if(requestDetails.isoipcreview) { - setShowOIPCDetails(true); + setIsOIPCReview(true); } else { - setShowOIPCDetails(false); + setIsOIPCReview(false); } }, [requestDetails]); @@ -349,7 +348,7 @@ const FOIRequest = React.memo(({ userDetail }) => { useEffect(() => { if(Object.keys(requestDetails).length !== 0 && oipcData?.length <= 0) { requestDetails.isoipcreview = false; - setShowOIPCDetails(false); + setIsOIPCReview(false); } }, [oipcData]) @@ -651,7 +650,8 @@ const FOIRequest = React.memo(({ userDetail }) => { const oipcSectionRef = React.useRef(null); const handleOipcReviewFlagChange = (isSelected) => { - setShowOIPCDetails(isSelected); + setIsOIPCReview(isSelected); + requestDetails.isoipcreview = isSelected; oipcSectionRef.current.scrollIntoView(); //timeout to allow react state to update after setState call if (isSelected) { @@ -1135,7 +1135,7 @@ const FOIRequest = React.memo(({ userDetail }) => { disableInput={disableInput} isAddRequest={isAddRequest} handleOipcReviewFlagChange={handleOipcReviewFlagChange} - showOipcReviewFlag={requestState.toLowerCase() !== StateEnum.intakeinprogress.name.toLowerCase()} + showOipcReviewFlag={requestState.toLowerCase() !== StateEnum.intakeinprogress.name.toLowerCase() && requestState.toLowerCase() !== StateEnum.unopened.name.toLowerCase()} /> {(isAddRequest || requestState === StateEnum.unopened.name) && ( @@ -1252,7 +1252,7 @@ const FOIRequest = React.memo(({ userDetail }) => { /> )}
- {showOIPCDetails && requestState && requestState.toLowerCase() !== StateEnum.intakeinprogress.name.toLowerCase() && ( + {isOIPCReview && requestState && requestState.toLowerCase() !== StateEnum.intakeinprogress.name.toLowerCase() && requestState.toLowerCase() !== StateEnum.unopened.name.toLowerCase() && ( { const [_currentrequestStatus, setcurrentrequestStatus] = React.useState(""); const [_tabStatus, settabStatus] = React.useState(requestState); - const {oipcData, addOIPC, removeOIPC, updateOIPC} = useOIPCHook(); - const [showOIPCDetails, setShowOIPCDetails] = useState(requestDetails.oipcData?.length > 0); + const {oipcData, addOIPC, removeOIPC, updateOIPC, isOIPCReview, setIsOIPCReview} = useOIPCHook(); + //gets the request detail from the store const IsDivisionalCoordinator = () => { return userDetail?.role?.includes("DivisionalCoordinator"); @@ -588,7 +588,8 @@ const MinistryReview = React.memo(({ userDetail }) => { const oipcSectionRef = React.useRef(null); const handleOipcReviewFlagChange = (isSelected) => { - setShowOIPCDetails(isSelected); + setIsOIPCReview(isSelected); + requestDetails.isoipcreview = isSelected; oipcSectionRef.current.scrollIntoView(); //timeout to allow react state to update after setState call if (isSelected) { @@ -785,7 +786,7 @@ const MinistryReview = React.memo(({ userDetail }) => { {divisionsBox} {/* */}
- {showOIPCDetails && requestState && requestState.toLowerCase() !== StateEnum.intakeinprogress.name.toLowerCase() && ( + {isOIPCReview && requestState && requestState.toLowerCase() !== StateEnum.intakeinprogress.name.toLowerCase() && requestState.toLowerCase() !== StateEnum.unopened.name.toLowerCase() && ( { //OIPC State const requestDetails = useSelector((state) => state.foiRequests.foiRequestDetail); const stageOIPCData = (isoipcreview, oipcData) => { + console.log(isoipcreview) if (isoipcreview) { if (oipcData?.length > 0) { return oipcData.map((item, index) => { @@ -31,11 +32,12 @@ const useOIPCHook = () => { } } const [oipcData, setOipcData] = useState(requestDetails.oipcdetails); + const [isOIPCReview, setIsOIPCReview] = useState(requestDetails.isoipcreview); useEffect(() => { - const stagedOIPCData = stageOIPCData(requestDetails.isoipcreview, requestDetails.oipcdetails); + const stagedOIPCData = stageOIPCData(isOIPCReview, requestDetails.oipcdetails); setOipcData(stagedOIPCData); - }, [requestDetails]) + }, [isOIPCReview]) console.log("HOOK", oipcData) @@ -88,6 +90,8 @@ const useOIPCHook = () => { updateOIPC, stageOIPCData, removeAllOIPCs, + isOIPCReview, + setIsOIPCReview, }; }; From 10da09b1594b9e5e6666416ef47f7d843b03db67 Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Tue, 28 Nov 2023 19:42:18 -0800 Subject: [PATCH 059/238] Add flags column to advanced search --- .../Ministry/AdvancedSearch/DataGridAdvancedSearch.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/forms-flow-web/src/components/FOI/Dashboard/Ministry/AdvancedSearch/DataGridAdvancedSearch.js b/forms-flow-web/src/components/FOI/Dashboard/Ministry/AdvancedSearch/DataGridAdvancedSearch.js index 11be2fbeb..fa6955135 100644 --- a/forms-flow-web/src/components/FOI/Dashboard/Ministry/AdvancedSearch/DataGridAdvancedSearch.js +++ b/forms-flow-web/src/components/FOI/Dashboard/Ministry/AdvancedSearch/DataGridAdvancedSearch.js @@ -8,7 +8,8 @@ import { updateSortModel, getLDD, getRecordsDue, - LightTooltip + LightTooltip, + displayQueueFlagIcons } from "../../utils"; import { ActionContext } from "./ActionContext"; import { ConditionalComponent } from "../../../../../helper/FOI/helper"; @@ -94,6 +95,12 @@ const DataGridAdvancedSearch = ({ userDetail }) => { }; const columns = React.useRef([ + { + field: "flags", + headerName: "FLAGS", + headerAlign: "left", + renderCell: displayQueueFlagIcons, + }, { field: "axisRequestId", headerName: "ID NUMBER", From 8b81caca7b984c2a143bc4c4fee9bbd55e1d1891 Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Tue, 28 Nov 2023 20:44:49 -0800 Subject: [PATCH 060/238] Add validation and master data to MinistryReview --- .../FOIRequest/MinistryReview/MinistryReview.js | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js index ee57d2c08..8e8cc00c1 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js @@ -18,6 +18,10 @@ import { import { fetchFOIMinistryAssignedToList, fetchFOIPersonalDivisionsAndSections, + fetchOIPCInquiryoutcomes, + fetchOIPCOutcomes, + fetchOIPCReviewtypes, + fetchOIPCStatuses, } from "../../../../apiManager/services/FOI/foiMasterDataServices"; import { fetchFOIRequestAttachmentsList } from "../../../../apiManager/services/FOI/foiAttachmentServices"; @@ -214,6 +218,12 @@ const MinistryReview = React.memo(({ userDetail }) => { dispatch(fetchPDFStitchStatusForHarms(requestId, ministryId)); dispatch(fetchPDFStitchStatusForRedlines(requestId, ministryId)); dispatch(fetchPDFStitchStatusForResponsePackage(requestId, ministryId)); + + dispatch(fetchOIPCOutcomes()); + dispatch(fetchOIPCStatuses()); + dispatch(fetchOIPCReviewtypes()); + dispatch(fetchOIPCInquiryoutcomes()); + fetchCFRForm(ministryId, dispatch); if (bcgovcode) dispatch(fetchFOIMinistryAssignedToList(bcgovcode)); } @@ -322,6 +332,11 @@ const MinistryReview = React.memo(({ userDetail }) => { hasincompleteDivstage || !hasReceivedDate; + const isOipcReviewValidationError = (oipcData?.length > 0 && requestDetails.isoipcreview && oipcData?.some((oipc) => { + return oipc.oipcno === "" || oipc.receiveddate === null || oipc.receiveddate === "" || oipc.reviewtypeid === null || oipc.reasonid === null || oipc.statusid === null || + oipc.inquiryattributes?.orderno === "" || oipc.inquiryattributes?.inquiryoutcome === null || oipc.inquiryattributes?.inquirydate === null || oipc.inquiryattributes?.inquirydate === ""; + })) + const createMinistrySaveRequestObject = (_propName, _value, _value2) => { const requestObject = { ...saveMinistryRequestObject }; setUnSavedRequest(true); @@ -798,7 +813,7 @@ const MinistryReview = React.memo(({ userDetail }) => { requestState={requestState} stateChanged={stateChanged} attachmentsArray={requestAttachments} - isValidationError={isValidationError} + isValidationError={isValidationError || isOipcReviewValidationError} saveMinistryRequestObject={saveMinistryRequestObject} unSavedRequest={unSavedRequest} recordsUploading={recordsUploading} From fb170847891ad1d61cf1af192c4e2a3ddd399660 Mon Sep 17 00:00:00 2001 From: "sumathi.thirumani" Date: Wed, 29 Nov 2023 00:08:11 -0800 Subject: [PATCH 061/238] Comment phased release. --- forms-flow-web/src/components/FOI/Dashboard/utils.js | 1 - .../src/components/FOI/FOIRequest/FOIRequestHeader/index.js | 4 ++-- .../components/FOI/FOIRequest/MinistryReview/RequestHeader.js | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/forms-flow-web/src/components/FOI/Dashboard/utils.js b/forms-flow-web/src/components/FOI/Dashboard/utils.js index a363e303e..a8374d54c 100644 --- a/forms-flow-web/src/components/FOI/Dashboard/utils.js +++ b/forms-flow-web/src/components/FOI/Dashboard/utils.js @@ -255,7 +255,6 @@ export const displayQueueFlagIcons = (params) => { return
{restricted} {oipcreview} - {/* {phasedrelease} */}
} diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js index 48f92607f..8b878d685 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js @@ -292,12 +292,12 @@ const FOIRequestHeader = React.memo( handleSelect={handleOipcReviewFlagChange} showFlag={showOipcReviewFlag} /> - + /> */}
diff --git a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/RequestHeader.js b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/RequestHeader.js index a8e1176d9..08df3663a 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/RequestHeader.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/RequestHeader.js @@ -111,12 +111,12 @@ const RequestHeader = React.memo(({ isActive={requestDetails.isoipcreview} handleSelect={handleOipcReviewFlagChange} /> - console.log('selected')} - /> + /> */}
); return ( From a554b03f7f1e6b6fa53465db76d3dd1d8dad8023 Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Wed, 29 Nov 2023 14:28:01 -0800 Subject: [PATCH 062/238] Remove OIPC from ministry view --- .../MinistryReview/MinistryReview.js | 26 ------------------- .../MinistryReview/RequestHeader.js | 5 +--- 2 files changed, 1 insertion(+), 30 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js index ee57d2c08..bb181645c 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js @@ -62,8 +62,6 @@ import { UnsavedModal } from "../../customComponents"; import { DISABLE_GATHERINGRECORDS_TAB } from "../../../../constants/constants"; import _ from "lodash"; import { MinistryNeedsScanning } from "../../../../constants/FOI/enum"; -import OIPCDetails from "../OIPCDetails/Index"; -import useOIPCHook from "../OIPCDetails/oipcHook"; const useStyles = makeStyles((theme) => ({ root: { @@ -110,7 +108,6 @@ const MinistryReview = React.memo(({ userDetail }) => { const [_currentrequestStatus, setcurrentrequestStatus] = React.useState(""); const [_tabStatus, settabStatus] = React.useState(requestState); - const {oipcData, addOIPC, removeOIPC, updateOIPC, isOIPCReview, setIsOIPCReview} = useOIPCHook(); //gets the request detail from the store const IsDivisionalCoordinator = () => { @@ -586,19 +583,6 @@ const MinistryReview = React.memo(({ userDetail }) => { (state) => state.foiRequests.showEventQueue ); - const oipcSectionRef = React.useRef(null); - const handleOipcReviewFlagChange = (isSelected) => { - setIsOIPCReview(isSelected); - requestDetails.isoipcreview = isSelected; - oipcSectionRef.current.scrollIntoView(); - //timeout to allow react state to update after setState call - if (isSelected) { - setTimeout(() => { - oipcSectionRef.current.scrollIntoView(); - }, (10)); - } - } - return !isLoading && requestDetails && Object.keys(requestDetails).length !== 0 && @@ -769,7 +753,6 @@ const MinistryReview = React.memo(({ userDetail }) => { setSaveMinistryRequestObject } ministryAssigneeValue={ministryAssignedToValue} - handleOipcReviewFlagChange={handleOipcReviewFlagChange} /> @@ -785,15 +768,6 @@ const MinistryReview = React.memo(({ userDetail }) => { /> {divisionsBox} {/* */} -
- {isOIPCReview && requestState && requestState.toLowerCase() !== StateEnum.intakeinprogress.name.toLowerCase() && requestState.toLowerCase() !== StateEnum.unopened.name.toLowerCase() && ( - - )} { const { requestId, ministryId } = useParams(); const _requestDetails = requestDetails; @@ -109,13 +108,11 @@ const RequestHeader = React.memo(({ type="oipcreview" requestDetails={requestDetails} isActive={requestDetails.isoipcreview} - handleSelect={handleOipcReviewFlagChange} /> console.log('selected')} />
); From 59bf1eb7ed0a9dac3f76f51d63eb613e4667f90e Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Wed, 29 Nov 2023 17:06:39 -0800 Subject: [PATCH 063/238] Add useEffect to sync flag to state --- .../src/components/FOI/customComponents/RequestFlag.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js b/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js index 1109fe8b4..dc1ab85dc 100644 --- a/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js +++ b/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js @@ -1,4 +1,4 @@ -import { useState } from "react"; +import { useEffect, useState } from "react"; import "./requestflag.scss"; import OutlinedInput from "@material-ui/core/OutlinedInput"; import MenuItem from "@material-ui/core/MenuItem"; @@ -28,6 +28,10 @@ const RequestFlag = ({ isActive, type, handleSelect, showFlag = true }) => { const { requestId, ministryId } = useParams(); + useEffect(() => { + setIsSelected(isActive); + }, [isActive]) + const dispatch = useDispatch(); // These need to be set for each type From ff59c3c24cb2796f6c3b329d842059762b71bffb Mon Sep 17 00:00:00 2001 From: "sumathi.thirumani" Date: Wed, 29 Nov 2023 23:31:41 -0800 Subject: [PATCH 064/238] Cosmetic changes for dropdown. --- forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js | 3 +-- .../components/FOI/FOIRequest/FOIRequestHeader/index.js | 7 ++++++- .../FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx | 1 - .../src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js | 3 +-- .../src/components/FOI/customComponents/requestflag.scss | 4 +++- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index 7532dd07f..64f95c009 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -352,8 +352,7 @@ const FOIRequest = React.memo(({ userDetail }) => { } }, [oipcData]) - console.log(requestDetails) - + useEffect(() => { if (isIAORestricted) dispatch(fetchRestrictedRequestCommentTagList(requestId, ministryId)); diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js index 8b878d685..69c3ed18f 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js @@ -36,6 +36,9 @@ const useStyles = makeStyles((theme) => ({ fontWeight: theme.typography.fontWeightBold, opacity: 1, }, + blankrow: { + padding: 25 + } })); const FOIRequestHeader = React.memo( ({ @@ -282,10 +285,12 @@ const FOIRequestHeader = React.memo( isIAORestrictedFileManager={isIAORestrictedFileManager()} requestDetails={requestDetails} /> + }
-
+ { const {oipcData, removeOIPC, updateOIPC} = props; - console.log("COMPONENT", oipcData) const OIPCItems = oipcData?.map((oipcObj, index) => { return ( <> diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js index 15a91f0cf..5cdf4b4a5 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js @@ -39,8 +39,7 @@ const useOIPCHook = () => { setOipcData(stagedOIPCData); }, [isOIPCReview]) - console.log("HOOK", oipcData) - + //OIPC Functions const addOIPC = () => { setOipcData((prev) => { diff --git a/forms-flow-web/src/components/FOI/customComponents/requestflag.scss b/forms-flow-web/src/components/FOI/customComponents/requestflag.scss index 4eb12f1e6..f9ac8c120 100644 --- a/forms-flow-web/src/components/FOI/customComponents/requestflag.scss +++ b/forms-flow-web/src/components/FOI/customComponents/requestflag.scss @@ -1,6 +1,7 @@ .request-flag { - margin-left: 15px; + margin-left: -50px; + padding-top: 50px; .request-flag-dropdown-all { padding-top: 10px; @@ -76,3 +77,4 @@ padding-top: 25px; } + From 348534510cb24d18b50f320bde70e6c2de906699 Mon Sep 17 00:00:00 2001 From: "sumathi.thirumani" Date: Wed, 29 Nov 2023 23:55:27 -0800 Subject: [PATCH 065/238] Enabling cache --- .../services/external/keycloakadminservice.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/request-management-api/request_api/services/external/keycloakadminservice.py b/request-management-api/request_api/services/external/keycloakadminservice.py index 3a632d34b..5ec6af21e 100644 --- a/request-management-api/request_api/services/external/keycloakadminservice.py +++ b/request-management-api/request_api/services/external/keycloakadminservice.py @@ -24,8 +24,8 @@ class KeycloakAdminService: def get_token(self): _accesstoken=None try: - #cache_client = redis.from_url(self.cache_redis_url,decode_responses=True) - _accesstoken = None #cache_client.get("foi:kcsrcacnttoken") + cache_client = redis.from_url(self.cache_redis_url,decode_responses=True) + _accesstoken = cache_client.get("foi:kcsrcacnttoken") if _accesstoken is None: url = '{0}/auth/realms/{1}/protocol/openid-connect/token'.format(self.keycloakhost,self.keycloakrealm) params = { @@ -38,11 +38,11 @@ def get_token(self): } x = requests.post(url, params, verify=True).content.decode('utf-8') _accesstoken = str(ast.literal_eval(x)['access_token']) - #cache_client.set("foi:kcsrcacnttoken",_accesstoken,ex=int(self.kctokenexpiry)) + cache_client.set("foi:kcsrcacnttoken",_accesstoken,ex=int(self.kctokenexpiry)) except BusinessException as exception: print("Error happened while accessing token on KeycloakAdminService {0}".format(exception.message)) - # finally: - # cache_client = None + finally: + cache_client = None return _accesstoken From 2c036198cea660b5e678e5801cdda485702e5fb7 Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Thu, 30 Nov 2023 09:23:42 -0800 Subject: [PATCH 066/238] Remove OIPC from ministryreview --- .../FOIRequest/MinistryReview/MinistryReview.js | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js index f620c7b60..bb181645c 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js @@ -18,10 +18,6 @@ import { import { fetchFOIMinistryAssignedToList, fetchFOIPersonalDivisionsAndSections, - fetchOIPCInquiryoutcomes, - fetchOIPCOutcomes, - fetchOIPCReviewtypes, - fetchOIPCStatuses, } from "../../../../apiManager/services/FOI/foiMasterDataServices"; import { fetchFOIRequestAttachmentsList } from "../../../../apiManager/services/FOI/foiAttachmentServices"; @@ -215,12 +211,6 @@ const MinistryReview = React.memo(({ userDetail }) => { dispatch(fetchPDFStitchStatusForHarms(requestId, ministryId)); dispatch(fetchPDFStitchStatusForRedlines(requestId, ministryId)); dispatch(fetchPDFStitchStatusForResponsePackage(requestId, ministryId)); - - dispatch(fetchOIPCOutcomes()); - dispatch(fetchOIPCStatuses()); - dispatch(fetchOIPCReviewtypes()); - dispatch(fetchOIPCInquiryoutcomes()); - fetchCFRForm(ministryId, dispatch); if (bcgovcode) dispatch(fetchFOIMinistryAssignedToList(bcgovcode)); } @@ -329,11 +319,6 @@ const MinistryReview = React.memo(({ userDetail }) => { hasincompleteDivstage || !hasReceivedDate; - const isOipcReviewValidationError = (oipcData?.length > 0 && requestDetails.isoipcreview && oipcData?.some((oipc) => { - return oipc.oipcno === "" || oipc.receiveddate === null || oipc.receiveddate === "" || oipc.reviewtypeid === null || oipc.reasonid === null || oipc.statusid === null || - oipc.inquiryattributes?.orderno === "" || oipc.inquiryattributes?.inquiryoutcome === null || oipc.inquiryattributes?.inquirydate === null || oipc.inquiryattributes?.inquirydate === ""; - })) - const createMinistrySaveRequestObject = (_propName, _value, _value2) => { const requestObject = { ...saveMinistryRequestObject }; setUnSavedRequest(true); @@ -787,7 +772,7 @@ const MinistryReview = React.memo(({ userDetail }) => { requestState={requestState} stateChanged={stateChanged} attachmentsArray={requestAttachments} - isValidationError={isValidationError || isOipcReviewValidationError} + isValidationError={isValidationError} saveMinistryRequestObject={saveMinistryRequestObject} unSavedRequest={unSavedRequest} recordsUploading={recordsUploading} From 9ca5ccdae5926081d5ce57a5e151c36bd49174d8 Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Thu, 30 Nov 2023 09:27:50 -0800 Subject: [PATCH 067/238] Remove unused imports --- .../src/components/FOI/customComponents/RequestFlag.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js b/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js index dc1ab85dc..9bfd6cbaa 100644 --- a/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js +++ b/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js @@ -13,8 +13,6 @@ import DialogTitle from "@material-ui/core/DialogTitle"; import CloseIcon from "@material-ui/icons/Close"; import IconButton from "@material-ui/core/IconButton"; import TextField from "@mui/material/TextField"; -import { useParams } from "react-router-dom"; -import { useDispatch } from "react-redux"; //Types are: //oipcreview @@ -26,14 +24,10 @@ const RequestFlag = ({ isActive, type, handleSelect, showFlag = true }) => { const [modalMessage, setModalMessage] = useState(""); const [modalDescription, setModalDescription] = useState(""); - const { requestId, ministryId } = useParams(); - useEffect(() => { setIsSelected(isActive); }, [isActive]) - const dispatch = useDispatch(); - // These need to be set for each type let options; let id; From b4424c575e7f78990305802657688e3b48f777fb Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Thu, 30 Nov 2023 09:47:56 -0800 Subject: [PATCH 068/238] Undo accidental commit --- .../services/external/keycloakadminservice.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/request-management-api/request_api/services/external/keycloakadminservice.py b/request-management-api/request_api/services/external/keycloakadminservice.py index 3a632d34b..57fe4536d 100644 --- a/request-management-api/request_api/services/external/keycloakadminservice.py +++ b/request-management-api/request_api/services/external/keycloakadminservice.py @@ -24,8 +24,8 @@ class KeycloakAdminService: def get_token(self): _accesstoken=None try: - #cache_client = redis.from_url(self.cache_redis_url,decode_responses=True) - _accesstoken = None #cache_client.get("foi:kcsrcacnttoken") + cache_client = redis.from_url(self.cache_redis_url,decode_responses=True) + _accesstoken = cache_client.get("foi:kcsrcacnttoken") if _accesstoken is None: url = '{0}/auth/realms/{1}/protocol/openid-connect/token'.format(self.keycloakhost,self.keycloakrealm) params = { @@ -38,11 +38,11 @@ def get_token(self): } x = requests.post(url, params, verify=True).content.decode('utf-8') _accesstoken = str(ast.literal_eval(x)['access_token']) - #cache_client.set("foi:kcsrcacnttoken",_accesstoken,ex=int(self.kctokenexpiry)) + cache_client.set("foi:kcsrcacnttoken",_accesstoken,ex=int(self.kctokenexpiry)) except BusinessException as exception: print("Error happened while accessing token on KeycloakAdminService {0}".format(exception.message)) - # finally: - # cache_client = None + finally: + cache_client = None return _accesstoken From 05f40331f652a5beffb35f37737303b14f282339 Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Thu, 30 Nov 2023 09:49:48 -0800 Subject: [PATCH 069/238] Match origin/main --- .../request_api/services/external/keycloakadminservice.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/request-management-api/request_api/services/external/keycloakadminservice.py b/request-management-api/request_api/services/external/keycloakadminservice.py index 57fe4536d..5b33b04ef 100644 --- a/request-management-api/request_api/services/external/keycloakadminservice.py +++ b/request-management-api/request_api/services/external/keycloakadminservice.py @@ -25,7 +25,7 @@ def get_token(self): _accesstoken=None try: cache_client = redis.from_url(self.cache_redis_url,decode_responses=True) - _accesstoken = cache_client.get("foi:kcsrcacnttoken") + _accesstoken = cache_client.get("foi:kcsrcacnttoken") if _accesstoken is None: url = '{0}/auth/realms/{1}/protocol/openid-connect/token'.format(self.keycloakhost,self.keycloakrealm) params = { @@ -42,7 +42,7 @@ def get_token(self): except BusinessException as exception: print("Error happened while accessing token on KeycloakAdminService {0}".format(exception.message)) finally: - cache_client = None + cache_client = None return _accesstoken From 3b83933e68f52560c48cef416cdeb0cb2ee5105d Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Thu, 30 Nov 2023 09:52:01 -0800 Subject: [PATCH 070/238] Add spaces to match main --- .../request_api/services/external/keycloakadminservice.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/request-management-api/request_api/services/external/keycloakadminservice.py b/request-management-api/request_api/services/external/keycloakadminservice.py index 5b33b04ef..f11fa992f 100644 --- a/request-management-api/request_api/services/external/keycloakadminservice.py +++ b/request-management-api/request_api/services/external/keycloakadminservice.py @@ -25,7 +25,7 @@ def get_token(self): _accesstoken=None try: cache_client = redis.from_url(self.cache_redis_url,decode_responses=True) - _accesstoken = cache_client.get("foi:kcsrcacnttoken") + _accesstoken = cache_client.get("foi:kcsrcacnttoken") if _accesstoken is None: url = '{0}/auth/realms/{1}/protocol/openid-connect/token'.format(self.keycloakhost,self.keycloakrealm) params = { @@ -42,7 +42,7 @@ def get_token(self): except BusinessException as exception: print("Error happened while accessing token on KeycloakAdminService {0}".format(exception.message)) finally: - cache_client = None + cache_client = None return _accesstoken From ba3f9b5b07157c24735e039b7099d7770e7a47ae Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Thu, 30 Nov 2023 09:53:01 -0800 Subject: [PATCH 071/238] Add white space --- .../request_api/services/external/keycloakadminservice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/request-management-api/request_api/services/external/keycloakadminservice.py b/request-management-api/request_api/services/external/keycloakadminservice.py index f11fa992f..5ec6af21e 100644 --- a/request-management-api/request_api/services/external/keycloakadminservice.py +++ b/request-management-api/request_api/services/external/keycloakadminservice.py @@ -25,7 +25,7 @@ def get_token(self): _accesstoken=None try: cache_client = redis.from_url(self.cache_redis_url,decode_responses=True) - _accesstoken = cache_client.get("foi:kcsrcacnttoken") + _accesstoken = cache_client.get("foi:kcsrcacnttoken") if _accesstoken is None: url = '{0}/auth/realms/{1}/protocol/openid-connect/token'.format(self.keycloakhost,self.keycloakrealm) params = { From 2736d2e605525656f522c98623f84fd0469b423a Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Thu, 30 Nov 2023 11:34:31 -0800 Subject: [PATCH 072/238] Consoles to debug delete refresh issue --- forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js | 2 ++ .../components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx | 2 ++ .../src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js | 2 ++ 3 files changed, 6 insertions(+) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index 64f95c009..d6132bbc2 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -919,6 +919,8 @@ const FOIRequest = React.memo(({ userDetail }) => { requestState !== StateEnum.appfeeowing.name && requestDetails?.requestType === FOI_COMPONENT_CONSTANTS.REQUEST_TYPE_GENERAL) } + + console.log("REQ OBJ", requestDetails) return (!isLoading && requestDetails && diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx index a4c825ce8..f8d67c07c 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx @@ -5,6 +5,8 @@ import './oipcdetails.scss'; const OIPCDetailsList = (props) => { const {oipcData, removeOIPC, updateOIPC} = props; + console.log("COMPONENT", oipcData) + const OIPCItems = oipcData?.map((oipcObj, index) => { return ( <> diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js index 5cdf4b4a5..c7d6da1ad 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js @@ -39,6 +39,8 @@ const useOIPCHook = () => { setOipcData(stagedOIPCData); }, [isOIPCReview]) + console.log("HOOK", oipcData) + //OIPC Functions const addOIPC = () => { From cd04784086410dcdd939e0ff1cc9bc1579b106f1 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Thu, 30 Nov 2023 12:16:23 -0800 Subject: [PATCH 073/238] Debugging for delete modal refrehs bug --- .../src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 6 ++++-- .../FOI/FOIRequest/OIPCDetails/RemoveOIPCModal.jsx | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index 483518590..10ebd19e3 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -22,6 +22,8 @@ const OIPCItem = (props) => { const [showDeleteModal, setShowDeleteModal] = useState(false); const [showOutcomeModal, setShowOutcomeModal] = useState(false); const [showAmendModal, setShowAmendModal] = useState(false); + + console.log("ITEM", oipc) //Functions const generateNamesFromOIPCId = (oipcObj) => { @@ -147,12 +149,12 @@ const OIPCItem = (props) => { return ( <> -
+
- {showDeleteModal && } + {showDeleteModal && } {showOutcomeModal && } {showAmendModal && } diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/RemoveOIPCModal.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/RemoveOIPCModal.jsx index 853c28b54..878d8bea8 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/RemoveOIPCModal.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/RemoveOIPCModal.jsx @@ -10,12 +10,12 @@ const RemoveOIPCModal= ({ showModal, removeOIPC, setShowModal, - oipcid, + oipc, }) =>{ const handleSave = () => { setShowModal(false); - removeOIPC(oipcid) + removeOIPC(oipc.id) }; const handleClose = () => { setShowModal(false); From 3e3d313f494849d83a920668c0723242987d3e2e Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Thu, 30 Nov 2023 12:25:48 -0800 Subject: [PATCH 074/238] Adjust to previous merge --- .../src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index 10ebd19e3..507665ebf 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -154,7 +154,7 @@ const OIPCItem = (props) => {
- {showDeleteModal && } + {showDeleteModal && } {showOutcomeModal && } {showAmendModal && } From 0616672c6e09dd5323ad6cf456cea0a9fe83b9f4 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Thu, 30 Nov 2023 13:15:31 -0800 Subject: [PATCH 075/238] removal of debug code not needed --- .../src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index 507665ebf..0d998b9e2 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -149,7 +149,7 @@ const OIPCItem = (props) => { return ( <> -
+
From bee4d5942d6f95f72763e756a19a0092c031f5ea Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Thu, 30 Nov 2023 13:27:38 -0800 Subject: [PATCH 076/238] Add e.preventDefault --- .../src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index 483518590..819bb1cee 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -148,7 +148,10 @@ const OIPCItem = (props) => { return ( <>
-
From 4461f9d868a467ca11ed8ea015630a7ebeb8ee28 Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Thu, 30 Nov 2023 13:29:36 -0800 Subject: [PATCH 077/238] Undo previous commit --- .../src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index 819bb1cee..483518590 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -148,10 +148,7 @@ const OIPCItem = (props) => { return ( <>
-
From 59237f78e13e37f318987c240b1ec59ad9f1c3f4 Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Thu, 30 Nov 2023 13:30:43 -0800 Subject: [PATCH 078/238] Add e.preventDefault --- .../src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index 0d998b9e2..07401afc7 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -150,7 +150,10 @@ const OIPCItem = (props) => { return ( <>
-
From d1241350a0e45ae24d134ef47d00919e8274a4d0 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Thu, 30 Nov 2023 14:14:01 -0800 Subject: [PATCH 079/238] removal of console logs --- forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js | 2 -- .../components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx | 2 -- .../src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 2 -- .../src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js | 2 -- 4 files changed, 8 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index d6132bbc2..64f95c009 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -919,8 +919,6 @@ const FOIRequest = React.memo(({ userDetail }) => { requestState !== StateEnum.appfeeowing.name && requestDetails?.requestType === FOI_COMPONENT_CONSTANTS.REQUEST_TYPE_GENERAL) } - - console.log("REQ OBJ", requestDetails) return (!isLoading && requestDetails && diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx index f8d67c07c..a4c825ce8 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsList.jsx @@ -5,8 +5,6 @@ import './oipcdetails.scss'; const OIPCDetailsList = (props) => { const {oipcData, removeOIPC, updateOIPC} = props; - console.log("COMPONENT", oipcData) - const OIPCItems = oipcData?.map((oipcObj, index) => { return ( <> diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index 07401afc7..545480682 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -22,8 +22,6 @@ const OIPCItem = (props) => { const [showDeleteModal, setShowDeleteModal] = useState(false); const [showOutcomeModal, setShowOutcomeModal] = useState(false); const [showAmendModal, setShowAmendModal] = useState(false); - - console.log("ITEM", oipc) //Functions const generateNamesFromOIPCId = (oipcObj) => { diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js index c7d6da1ad..0d2a06c70 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js @@ -5,7 +5,6 @@ const useOIPCHook = () => { //OIPC State const requestDetails = useSelector((state) => state.foiRequests.foiRequestDetail); const stageOIPCData = (isoipcreview, oipcData) => { - console.log(isoipcreview) if (isoipcreview) { if (oipcData?.length > 0) { return oipcData.map((item, index) => { @@ -41,7 +40,6 @@ const useOIPCHook = () => { console.log("HOOK", oipcData) - //OIPC Functions const addOIPC = () => { setOipcData((prev) => { From 9973d3756294c506bae7193c86aea67933b1000d Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Thu, 30 Nov 2023 14:14:27 -0800 Subject: [PATCH 080/238] removal of console logs --- .../src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js index 0d2a06c70..55538aac9 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js @@ -38,7 +38,7 @@ const useOIPCHook = () => { setOipcData(stagedOIPCData); }, [isOIPCReview]) - console.log("HOOK", oipcData) + // console.log("HOOK", oipcData) //OIPC Functions const addOIPC = () => { From edc4765b87de43853cf5239d2c5a7e79e1d897cb Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Thu, 30 Nov 2023 16:31:43 -0800 Subject: [PATCH 081/238] Styling changes --- .../FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index 545480682..557f0c31d 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -194,13 +194,16 @@ const OIPCItem = (props) => { select variant="outlined" fullWidth - value={oipc.reviewtypeid} + value={oipc.reviewtypeid ? oipc.reviewtypeid : -1} label="Review Type" onChange={(event) => handleReviewType(event.target.value)} error={(!oipc.outcomeid || oipc.outcomeid === 5) && oipc.reviewtypeid === null} required disabled={oipc.outcomeid && oipc.outcomeid !== 5} > + + Select Review Type + {uniqueReviewTypes(oipcReviewtypes).map((reviewtype) => { return {reviewtype.type_name} })} @@ -212,13 +215,16 @@ const OIPCItem = (props) => { select variant="outlined" fullWidth - value={oipc.reasonid} + value={oipc.reasonid ? oipc.reasonid : -1} label="Reason" onChange = {(event) => handleReason(event.target.value)} error={(!oipc.outcomeid || oipc.outcomeid === 5) && oipc.reasonid === null} required disabled={oipc.outcomeid && oipc.outcomeid !== 5} > + + Select Review Type & Reason + {oipc.reviewtypeid ? oipcReviewtypes.map((reviewtype) => { if (reviewtype.reviewtypeid === oipc.reviewtypeid) { @@ -233,13 +239,16 @@ const OIPCItem = (props) => { select variant="outlined" fullWidth - value={oipc.statusid} + value={oipc.statusid ? oipc.statusid : -1} label="Status" onChange = {(event) => handleStatus(event.target.value)} error={(!oipc.outcomeid || oipc.outcomeid === 5) && oipc.statusid === null} required disabled={oipc.outcomeid && oipc.outcomeid !== 5} > + + Select Status + {oipcStatuses.map((status) => { return {status.name} })} @@ -264,9 +273,12 @@ const OIPCItem = (props) => { variant="outlined" onChange = {(event) => handleOutcome(event.target.value)} fullWidth - value={oipc.outcomeid} + value={oipc.outcomeid ? oipc.outcomeid : -1} label="Outcome" > + + Select Outcome + {oipcOutcomes.map((outcome) => { if (outcome.outcomeid !== 5) { return {outcome.name} From ea3da2e7538a3848117fc61c8fe28d2ab730e62c Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Thu, 30 Nov 2023 16:42:12 -0800 Subject: [PATCH 082/238] Default value stylying completed --- .../FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index 557f0c31d..a9f772b0e 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -202,7 +202,7 @@ const OIPCItem = (props) => { disabled={oipc.outcomeid && oipc.outcomeid !== 5} > - Select Review Type + Select Review Type {uniqueReviewTypes(oipcReviewtypes).map((reviewtype) => { return {reviewtype.type_name} @@ -223,7 +223,7 @@ const OIPCItem = (props) => { disabled={oipc.outcomeid && oipc.outcomeid !== 5} > - Select Review Type & Reason + Select Review Type & Reason {oipc.reviewtypeid ? oipcReviewtypes.map((reviewtype) => { @@ -247,7 +247,7 @@ const OIPCItem = (props) => { disabled={oipc.outcomeid && oipc.outcomeid !== 5} > - Select Status + Select Status {oipcStatuses.map((status) => { return {status.name} @@ -277,7 +277,7 @@ const OIPCItem = (props) => { label="Outcome" > - Select Outcome + Select Outcome {oipcOutcomes.map((outcome) => { if (outcome.outcomeid !== 5) { @@ -393,12 +393,15 @@ const OIPCItem = (props) => { variant="outlined" onChange = {(event) => handleInquiryFields(event.target.value, "INQUIRYOUTCOME")} fullWidth - value={oipc.inquiryattributes.inquiryoutcome} + value={oipc.inquiryattributes.inquiryoutcome ? oipc.inquiryattributes.inquiryoutcome : -1} label="Outcome" error={(!oipc.outcomeid || oipc.outcomeid === 5) && oipc.inquiryattributes.inquiryoutcome === null} required disabled={oipc.outcomeid && oipc.outcomeid !== 5} - > + > + + Select Inquiry Outcome + {oipcInquiryoutcomes.map((inquiryoutcome) => { return {inquiryoutcome.name} })} From 6d58e93a464277eb2339b8d2ed70a50883821576 Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Thu, 30 Nov 2023 17:13:16 -0800 Subject: [PATCH 083/238] Update disableInput when oipcData is changed --- .../components/FOI/FOIRequest/FOIRequest.js | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index d6132bbc2..2fab44743 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -163,8 +163,7 @@ const FOIRequest = React.memo(({ userDetail }) => { const [attachments, setAttachments] = useState(requestAttachments); const [comment, setComment] = useState([]); const [requestState, setRequestState] = useState(StateEnum.unopened.name); - const disableInput = - requestState?.toLowerCase() === StateEnum.closed.name.toLowerCase(); + const [disableInput, setDisableInput] = useState(requestState?.toLowerCase() === StateEnum.closed.name.toLowerCase()); const [_tabStatus, settabStatus] = React.useState(requestState); let foitabheaderBG = getTabBG(_tabStatus, requestState); @@ -258,7 +257,24 @@ const FOIRequest = React.memo(({ userDetail }) => { const [redactedSections, setRedactedSections] = useState(""); const [isMCFPersonal, setIsMCFPersonal] = useState(bcgovcode.replaceAll('"', '') == "MCF" && requestDetails.requestType == FOI_COMPONENT_CONSTANTS.REQUEST_TYPE_PERSONAL); const {oipcData, addOIPC, removeOIPC, updateOIPC, isOIPCReview, setIsOIPCReview} = useOIPCHook(); - + const [oipcDataInitial, setOipcDataInitial] = useState(oipcData); + + //Update disableInput when requestState changes + useEffect(() => { + setDisableInput(requestState?.toLowerCase() === StateEnum.closed.name.toLowerCase()) + }, [requestState]) + + useEffect(() => { + if (!oipcDataInitial) { + setOipcDataInitial(oipcData); + return; + } + //check to see if oipcData has been updated, if so, enable save button + if (JSON.stringify(oipcData) != JSON.stringify(oipcDataInitial)) { + setDisableInput(false) + } + }, [oipcData]); + useEffect(() => { if (window.location.href.indexOf("comments") > -1) { tabclick("Comments"); From cb95b335d236bf7e4dee863174156bae6a49c545 Mon Sep 17 00:00:00 2001 From: "sumathi.thirumani" Date: Thu, 30 Nov 2023 19:37:22 -0800 Subject: [PATCH 084/238] changes to avoid default reset of data. --- .../FOI/FOIRequest/OIPCDetails/oipcHook.js | 12 ++++++++++-- .../components/FOI/customComponents/requestflag.scss | 1 - 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js index 851651746..eb24abdd6 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js @@ -32,10 +32,12 @@ const useOIPCHook = () => { } const [oipcData, setOipcData] = useState(requestDetails.oipcdetails); const [isOIPCReview, setIsOIPCReview] = useState(requestDetails.isoipcreview); - + const [resettoInitial, setResettoInitial] = useState(false); useEffect(() => { + if (resettoInitial == false) { const stagedOIPCData = stageOIPCData(isOIPCReview, requestDetails.oipcdetails); setOipcData(stagedOIPCData); + } }, [isOIPCReview]) //OIPC Functions @@ -59,11 +61,17 @@ const useOIPCHook = () => { }) } const removeOIPC = (oipcId) => { + if (oipcData.length == 1) { + setOipcData([]); + setResettoInitial(true) + } + else { setOipcData((prev) => { const previousOIPCData = [...prev]; - return previousOIPCData.filter(oipc => oipcId !== oipc.id); + return previousOIPCData.filter(oipc => oipcId !== oipc.id); }); } + } const updateOIPC = (newOIPCObj) => { setOipcData((prev) => { const previousOIPCData = [...prev]; diff --git a/forms-flow-web/src/components/FOI/customComponents/requestflag.scss b/forms-flow-web/src/components/FOI/customComponents/requestflag.scss index f9ac8c120..7df546c97 100644 --- a/forms-flow-web/src/components/FOI/customComponents/requestflag.scss +++ b/forms-flow-web/src/components/FOI/customComponents/requestflag.scss @@ -1,6 +1,5 @@ .request-flag { - margin-left: -50px; padding-top: 50px; .request-flag-dropdown-all { From e1b7ea61109ee35e3dd37c46ffe142543b6b1b9a Mon Sep 17 00:00:00 2001 From: "sumathi.thirumani" Date: Thu, 30 Nov 2023 20:29:02 -0800 Subject: [PATCH 085/238] Remove important --- .../components/FOI/FOIRequest/OIPCDetails/oipcdetails.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcdetails.scss b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcdetails.scss index d28779da2..9d467ac10 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcdetails.scss +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcdetails.scss @@ -32,7 +32,7 @@ } .MuiDivider-root { - margin: 10px 0px 16px 0px !important; - height: 1.5px !important; + margin: 10px 0px 16px 0px; + height: 1.5px; } \ No newline at end of file From 9aef23e5c4dbe8204dced04fa7dafa83e7811256 Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Fri, 1 Dec 2023 09:46:40 -0800 Subject: [PATCH 086/238] Handle requests where isoipcreview is null --- .../src/components/FOI/customComponents/RequestFlag.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js b/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js index 9bfd6cbaa..3899502ec 100644 --- a/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js +++ b/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js @@ -25,7 +25,11 @@ const RequestFlag = ({ isActive, type, handleSelect, showFlag = true }) => { const [modalDescription, setModalDescription] = useState(""); useEffect(() => { + if (isActive == null) { + setIsSelected(false); + } else { setIsSelected(isActive); + } }, [isActive]) // These need to be set for each type From 1cc4b6234735988acb6c4c23cc166d2c324ec59b Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Fri, 1 Dec 2023 11:41:49 -0800 Subject: [PATCH 087/238] Bug fix. Selection of no review flag removes all oipcs even if flag goes back to oipc review --- .../src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js index eb24abdd6..965441ece 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcHook.js @@ -61,9 +61,9 @@ const useOIPCHook = () => { }) } const removeOIPC = (oipcId) => { - if (oipcData.length == 1) { + if (oipcData.length === 1) { setOipcData([]); - setResettoInitial(true) + setResettoInitial(true); } else { setOipcData((prev) => { @@ -86,6 +86,7 @@ const useOIPCHook = () => { } const removeAllOIPCs = () => { setOipcData([]); + setResettoInitial(true); } return { From 3a492540d9098825c8152af58b546380b47e5dab Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Fri, 1 Dec 2023 11:43:43 -0800 Subject: [PATCH 088/238] Bug fix. Selection of no review flag removes all oipcs even if flag goes back to oipc review --- forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index 2a55ca8c1..feb5e61ee 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -256,7 +256,7 @@ const FOIRequest = React.memo(({ userDetail }) => { const [isIAORestricted, setIsIAORestricted] = useState(false); const [redactedSections, setRedactedSections] = useState(""); const [isMCFPersonal, setIsMCFPersonal] = useState(bcgovcode.replaceAll('"', '') == "MCF" && requestDetails.requestType == FOI_COMPONENT_CONSTANTS.REQUEST_TYPE_PERSONAL); - const {oipcData, addOIPC, removeOIPC, updateOIPC, isOIPCReview, setIsOIPCReview} = useOIPCHook(); + const {oipcData, addOIPC, removeOIPC, updateOIPC, isOIPCReview, setIsOIPCReview, removeAllOIPCs} = useOIPCHook(); const [oipcDataInitial, setOipcDataInitial] = useState(oipcData); //Update disableInput when requestState changes @@ -665,6 +665,9 @@ const FOIRequest = React.memo(({ userDetail }) => { const oipcSectionRef = React.useRef(null); const handleOipcReviewFlagChange = (isSelected) => { + if (!isSelected) { + removeAllOIPCs(); + } setIsOIPCReview(isSelected); requestDetails.isoipcreview = isSelected; oipcSectionRef.current.scrollIntoView(); From 1da557598c287d3c01bb0e89c95bcbb0533de144 Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Fri, 1 Dec 2023 15:38:18 -0800 Subject: [PATCH 089/238] Add filter for closed requests with OIPC flag --- .../request_api/models/FOIMinistryRequests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index 8abc19dc7..7ac646528 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -562,7 +562,7 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us SubjectCode, SubjectCode.subjectcodeid == FOIMinistryRequestSubjectCode.subjectcodeid, isouter=True - ).filter(FOIMinistryRequest.requeststatusid != 3) + ).filter(or_(FOIMinistryRequest.requeststatusid != 3, and_(FOIMinistryRequest.isoipcreview == True, FOIMinistryRequest.requeststatusid == 3))) if(additionalfilter == 'watchingRequests'): #watchby From ed2700198a68b900a0c5cf2a9c8095b15894dd95 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Fri, 1 Dec 2023 16:40:09 -0800 Subject: [PATCH 090/238] Scenario 12 logic completed for ticket --- .../components/FOI/FOIRequest/FOIRequest.js | 24 ++++++++++++------- .../request_api/services/requestservice.py | 16 +++++++++++++ 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index feb5e61ee..948518158 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -790,14 +790,20 @@ const FOIRequest = React.memo(({ userDetail }) => { }; const handlestatusudpate = (_daysRemaining, _status, _cfrDaysRemaining) => { - const mappedBottomText = getTabBottomText({ - _daysRemaining, - _cfrDaysRemaining, - _status, - requestExtensions, - }); - - setRequestStatus(mappedBottomText); + const reopenedRequest = StateEnum.closed.name.toLowerCase() !== requestDetails.currentState.toLowerCase() && requestDetails.stateTransition.some((state) => state.status.toLowerCase() === StateEnum.closed.name.toLowerCase()); + if (reopenedRequest && isOIPCReview) { + console.log("reopened", reopenedRequest) + console.log("OIPC", isOIPCReview) + setRequestStatus(""); + } else { + const mappedBottomText = getTabBottomText({ + _daysRemaining, + _cfrDaysRemaining, + _status, + requestExtensions, + }); + setRequestStatus(mappedBottomText); + } }; const hasStatusRequestSaved = (state) => { @@ -939,6 +945,8 @@ const FOIRequest = React.memo(({ userDetail }) => { requestDetails?.requestType === FOI_COMPONENT_CONSTANTS.REQUEST_TYPE_GENERAL) } + console.log("REQ", requestDetails) + return (!isLoading && requestDetails && Object.keys(requestDetails).length !== 0) || diff --git a/request-management-api/request_api/services/requestservice.py b/request-management-api/request_api/services/requestservice.py index 83d6bf039..4c9b5601e 100644 --- a/request-management-api/request_api/services/requestservice.py +++ b/request-management-api/request_api/services/requestservice.py @@ -139,10 +139,14 @@ def calculateduedate(self, ministryrequestid, foirequest, paymentdate): def __skipduedatecalculation(self, ministryrequestid, offholddate): previousoffholddate = FOIMinistryRequest.getlastoffholddate(ministryrequestid) + foiministry_request = FOIMinistryRequest.getrequest(ministryrequestid) + request_reopened = self.__hasreopened(ministryrequestid, "ministryrequest") if previousoffholddate not in (None, ''): previouspaymentdate_pst = datetimehandler().convert_to_pst(previousoffholddate) if datetimehandler().getdate(previouspaymentdate_pst).date() == datetimehandler().getdate(offholddate).date(): return True + if foiministry_request['isoipcreview'] == True and request_reopened: + return True return False def __isincludeoffhold(self): @@ -165,4 +169,16 @@ def saverestrictedrequest(self,ministryrequestid,type, isrestricted,userid): version = FOIMinistryRequest.getversionforrequest(ministryrequestid) FOIRestrictedMinistryRequest.disablerestrictedrequests(ministryrequestid,type,userid) return FOIRestrictedMinistryRequest.saverestrictedrequest(ministryrequestid,type,isrestricted, version, userid) + + def __hasreopened(self, requestid, requesttype): + if requesttype == "rawrequest": + states = FOIRawRequest.getstatenavigation(requestid) + else: + states = FOIMinistryRequest.getstatenavigation(requestid) + if len(states) == 2: + newstate = states[0] + oldstate = states[1] + if newstate != oldstate and oldstate == "Closed": + return True + return False From b01d9309abaa4adca49b29522946c0be55892ef7 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Mon, 4 Dec 2023 09:25:52 -0800 Subject: [PATCH 091/238] removed mandatory requirement for inquiry fields --- .../src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 6 ------ forms-flow-web/src/components/FOI/FOIRequest/utils.js | 3 +-- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index a9f772b0e..1b10ef7a9 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -367,8 +367,6 @@ const OIPCItem = (props) => { InputLabelProps={{ shrink: true }} InputProps={{inputProps: { min: oipc.receiveddate ? formatDate(new Date(oipc.receiveddate)) : null } }} type="date" - error={(!oipc.outcomeid || oipc.outcomeid === 5) && oipc.inquiryattributes.inquirydate === null} - required disabled={oipc.outcomeid && oipc.outcomeid !== 5} /> @@ -380,8 +378,6 @@ const OIPCItem = (props) => { value={oipc.inquiryattributes.orderno} onChange = {(event) => handleInquiryFields(event.target.value, "ORDERNO")} InputLabelProps={{ shrink: true }} - error={(!oipc.outcomeid || oipc.outcomeid === 5) && oipc.inquiryattributes.orderno === ""} - required disabled={oipc.outcomeid && oipc.outcomeid !== 5} placeholder="Order Number" /> @@ -395,8 +391,6 @@ const OIPCItem = (props) => { fullWidth value={oipc.inquiryattributes.inquiryoutcome ? oipc.inquiryattributes.inquiryoutcome : -1} label="Outcome" - error={(!oipc.outcomeid || oipc.outcomeid === 5) && oipc.inquiryattributes.inquiryoutcome === null} - required disabled={oipc.outcomeid && oipc.outcomeid !== 5} > diff --git a/forms-flow-web/src/components/FOI/FOIRequest/utils.js b/forms-flow-web/src/components/FOI/FOIRequest/utils.js index 2905bfea2..486ae82f3 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/utils.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/utils.js @@ -349,8 +349,7 @@ export const checkValidationError = ( !requiredRequestDetailsValues.requestStartDate || !requiredAxisDetails.axisRequestId || (oipcData?.length > 0 && isOipcReview && oipcData?.some((oipc) => { - return oipc.oipcno === "" || oipc.receiveddate === null || oipc.receiveddate === "" || oipc.reviewtypeid === null || oipc.reasonid === null || oipc.statusid === null || - oipc.inquiryattributes?.orderno === "" || oipc.inquiryattributes?.inquiryoutcome === null || oipc.inquiryattributes?.inquirydate === null || oipc.inquiryattributes?.inquirydate === ""; + return oipc.oipcno === "" || oipc.receiveddate === null || oipc.receiveddate === "" || oipc.reviewtypeid === null || oipc.reasonid === null || oipc.statusid === null; })) ); }; From 42c591f7eed5c6717b296c8afbd2aaea8f0a0495 Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Mon, 4 Dec 2023 09:55:40 -0800 Subject: [PATCH 092/238] Update filter to include closed OIPC requests --- .../request_api/models/FOIMinistryRequests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index 8abc19dc7..7ac646528 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -562,7 +562,7 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us SubjectCode, SubjectCode.subjectcodeid == FOIMinistryRequestSubjectCode.subjectcodeid, isouter=True - ).filter(FOIMinistryRequest.requeststatusid != 3) + ).filter(or_(FOIMinistryRequest.requeststatusid != 3, and_(FOIMinistryRequest.isoipcreview == True, FOIMinistryRequest.requeststatusid == 3))) if(additionalfilter == 'watchingRequests'): #watchby From accaf799ec2f854e49bb9180ae3b069f9e440f6c Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Mon, 4 Dec 2023 13:03:31 -0800 Subject: [PATCH 093/238] Scenario 12 AC + Adjustment to inquiryatrbiute oipc validations for 4671 completed --- .../components/FOI/FOIRequest/FOIRequest.js | 24 +++++++------------ .../FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 6 ++++- .../src/components/FOI/FOIRequest/utils.js | 8 ++++++- .../foirequest/requestservicegetter.py | 10 ++++++++ 4 files changed, 31 insertions(+), 17 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index 948518158..81e661e06 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -790,20 +790,13 @@ const FOIRequest = React.memo(({ userDetail }) => { }; const handlestatusudpate = (_daysRemaining, _status, _cfrDaysRemaining) => { - const reopenedRequest = StateEnum.closed.name.toLowerCase() !== requestDetails.currentState.toLowerCase() && requestDetails.stateTransition.some((state) => state.status.toLowerCase() === StateEnum.closed.name.toLowerCase()); - if (reopenedRequest && isOIPCReview) { - console.log("reopened", reopenedRequest) - console.log("OIPC", isOIPCReview) - setRequestStatus(""); - } else { - const mappedBottomText = getTabBottomText({ - _daysRemaining, - _cfrDaysRemaining, - _status, - requestExtensions, - }); - setRequestStatus(mappedBottomText); - } + const mappedBottomText = getTabBottomText({ + _daysRemaining, + _cfrDaysRemaining, + _status, + requestExtensions, + }); + setRequestStatus(mappedBottomText); }; const hasStatusRequestSaved = (state) => { @@ -1053,7 +1046,8 @@ const FOIRequest = React.memo(({ userDetail }) => {
- {bottomTextArray.length > 0 && + {isOIPCReview && requestDetails.isreopened ? "" + : bottomTextArray.length > 0 && _requestStatus && _requestStatus.toLowerCase().includes("days") && bottomTextArray.map((text) => { diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index 1b10ef7a9..b70d30b71 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -183,7 +183,7 @@ const OIPCItem = (props) => { InputLabelProps={{ shrink: true }} InputProps={{inputProps: { max: formatDate(new Date())} }} type="date" - error={(!oipc.outcomeid || oipc.outcomeid === 5) && oipc.receiveddate === null} + error={(!oipc.outcomeid || oipc.outcomeid === 5) && oipc.receiveddate === null || oipc.receiveddate === ""} required disabled={oipc.outcomeid && oipc.outcomeid !== 5} /> @@ -367,6 +367,8 @@ const OIPCItem = (props) => { InputLabelProps={{ shrink: true }} InputProps={{inputProps: { min: oipc.receiveddate ? formatDate(new Date(oipc.receiveddate)) : null } }} type="date" + error={oipc.inquiryattributes.orderno ? (!oipc.outcomeid || oipc.outcomeid === 5) && oipc.inquiryattributes.inquirydate === null || oipc.inquiryattributes.inquirydate === "" : false} + required={oipc.inquiryattributes.orderno} disabled={oipc.outcomeid && oipc.outcomeid !== 5} /> @@ -378,6 +380,8 @@ const OIPCItem = (props) => { value={oipc.inquiryattributes.orderno} onChange = {(event) => handleInquiryFields(event.target.value, "ORDERNO")} InputLabelProps={{ shrink: true }} + error={oipc.inquiryattributes.inquirydate ? (!oipc.outcomeid || oipc.outcomeid === 5) && oipc.inquiryattributes.orderno === "" : false} + required={oipc.inquiryattributes.inquirydate} disabled={oipc.outcomeid && oipc.outcomeid !== 5} placeholder="Order Number" /> diff --git a/forms-flow-web/src/components/FOI/FOIRequest/utils.js b/forms-flow-web/src/components/FOI/FOIRequest/utils.js index 486ae82f3..dc5c8abeb 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/utils.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/utils.js @@ -349,7 +349,13 @@ export const checkValidationError = ( !requiredRequestDetailsValues.requestStartDate || !requiredAxisDetails.axisRequestId || (oipcData?.length > 0 && isOipcReview && oipcData?.some((oipc) => { - return oipc.oipcno === "" || oipc.receiveddate === null || oipc.receiveddate === "" || oipc.reviewtypeid === null || oipc.reasonid === null || oipc.statusid === null; + if (oipc.inquiryattributes?.inquirydate) { + return oipc.inquiryattributes.orderno === ""; + } + if (oipc.inquiryattributes?.orderno) { + return oipc.inquiryattributes?.inquirydate === null || oipc.inquiryattributes?.inquirydate === ""; + } + return oipc.oipcno === "" || oipc.receiveddate === null || oipc.receiveddate === "" || oipc.reviewtypeid === null || oipc.reasonid === null || oipc.statusid === null; })) ); }; diff --git a/request-management-api/request_api/services/foirequest/requestservicegetter.py b/request-management-api/request_api/services/foirequest/requestservicegetter.py index 78181e224..c3b431b00 100644 --- a/request-management-api/request_api/services/foirequest/requestservicegetter.py +++ b/request-management-api/request_api/services/foirequest/requestservicegetter.py @@ -168,6 +168,7 @@ def __preparebaseinfo(self,request,foiministryrequestid,requestministry,requestm 'selectedMinistries':[{'code':requestministry['programarea.bcgovcode'],'id':requestministry['foiministryrequestid'],'name':requestministry['programarea.name'],'selected':'true'}], 'divisions': self.getdivisions(requestministrydivisions), 'isoipcreview': requestministry['isoipcreview'], + 'isreopened': self.hasreopened(foiministryrequestid), 'oipcdetails': self.getoipcdetails(foiministryrequestid, requestministry['version']), 'onholdTransitionDate': self.getonholdtransition(foiministryrequestid), 'stateTransition': FOIMinistryRequest.getstatesummary(foiministryrequestid), @@ -268,6 +269,15 @@ def getministryrequest(self, foiministryrequestid): def __genericdateformat(self): return '%Y-%m-%d' + def hasreopened(self, requestid): + states = FOIMinistryRequest.getstatenavigation(requestid) + if len(states) == 2: + newstate = states[0] + oldstate = states[1] + if newstate != oldstate and oldstate == "Closed": + return True + return False + def __prepareapplicant(self,firstname= None, middlename= None, lastname= None, businessname= None): return { 'firstName': firstname, From 580645f0f08af656ea837e66c3533751d8a00117 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Mon, 4 Dec 2023 14:52:05 -0800 Subject: [PATCH 094/238] Adjusted Reopen logic in backend --- .../services/foirequest/requestservicegetter.py | 9 ++++----- .../request_api/services/requestservice.py | 12 +++++------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/request-management-api/request_api/services/foirequest/requestservicegetter.py b/request-management-api/request_api/services/foirequest/requestservicegetter.py index c3b431b00..6588bdb9f 100644 --- a/request-management-api/request_api/services/foirequest/requestservicegetter.py +++ b/request-management-api/request_api/services/foirequest/requestservicegetter.py @@ -270,11 +270,10 @@ def __genericdateformat(self): return '%Y-%m-%d' def hasreopened(self, requestid): - states = FOIMinistryRequest.getstatenavigation(requestid) - if len(states) == 2: - newstate = states[0] - oldstate = states[1] - if newstate != oldstate and oldstate == "Closed": + states = FOIMinistryRequest.getstatesummary(requestid) + if len(states) > 0: + current_state = states[0] + if current_state != "Closed" and any(state['status'] == "Closed" for state in states): return True return False diff --git a/request-management-api/request_api/services/requestservice.py b/request-management-api/request_api/services/requestservice.py index 4c9b5601e..99248b3d9 100644 --- a/request-management-api/request_api/services/requestservice.py +++ b/request-management-api/request_api/services/requestservice.py @@ -172,13 +172,11 @@ def saverestrictedrequest(self,ministryrequestid,type, isrestricted,userid): def __hasreopened(self, requestid, requesttype): if requesttype == "rawrequest": - states = FOIRawRequest.getstatenavigation(requestid) + states = FOIRawRequest.getstatesummary(requestid) else: - states = FOIMinistryRequest.getstatenavigation(requestid) - if len(states) == 2: - newstate = states[0] - oldstate = states[1] - if newstate != oldstate and oldstate == "Closed": + states = FOIMinistryRequest.getstatesummary(requestid) + if len(states) > 0: + current_state = states[0] + if current_state != "Closed" and any(state['status'] == "Closed" for state in states): return True return False - From e1038665f96b6c70f66446b9b6c2bbaad722bcce Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Mon, 4 Dec 2023 14:56:23 -0800 Subject: [PATCH 095/238] small code clean --- forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index 81e661e06..2deb1f15f 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -796,6 +796,7 @@ const FOIRequest = React.memo(({ userDetail }) => { _status, requestExtensions, }); + setRequestStatus(mappedBottomText); }; @@ -938,8 +939,6 @@ const FOIRequest = React.memo(({ userDetail }) => { requestDetails?.requestType === FOI_COMPONENT_CONSTANTS.REQUEST_TYPE_GENERAL) } - console.log("REQ", requestDetails) - return (!isLoading && requestDetails && Object.keys(requestDetails).length !== 0) || From ae26984a384e7a5c89384ebbc1e0b3207e3dc1b1 Mon Sep 17 00:00:00 2001 From: "sumathi.thirumani" Date: Tue, 5 Dec 2023 02:28:25 -0800 Subject: [PATCH 096/238] Draft changes. --- .../3e91d4f34699_oipc_notifications.py | 32 ++++ .../request_api/models/FOIMinistryRequests.py | 27 +++ .../models/OIPCReviewTypesReasons.py | 8 +- .../services/commons/duecalculator.py | 8 +- .../request_api/services/events/oipc.py | 155 ++++++++++++++++++ .../services/events/oipcduedate.py | 69 ++++++++ .../request_api/services/eventservice.py | 14 +- .../notifications/notificationconfig.py | 6 +- .../request_api/utils/enums.py | 1 + 9 files changed, 309 insertions(+), 11 deletions(-) create mode 100644 request-management-api/migrations/versions/3e91d4f34699_oipc_notifications.py create mode 100644 request-management-api/request_api/services/events/oipc.py create mode 100644 request-management-api/request_api/services/events/oipcduedate.py diff --git a/request-management-api/migrations/versions/3e91d4f34699_oipc_notifications.py b/request-management-api/migrations/versions/3e91d4f34699_oipc_notifications.py new file mode 100644 index 000000000..76141c027 --- /dev/null +++ b/request-management-api/migrations/versions/3e91d4f34699_oipc_notifications.py @@ -0,0 +1,32 @@ +"""empty message + +Revision ID: 3e91d4f34699 +Revises: 455a24da8c58 +Create Date: 2023-11-30 00:11:56.160830 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = '3e91d4f34699' +down_revision = '455a24da8c58' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.execute('Insert into public."NotificationTypes" (name, description, isactive) values (\'OIPC\', \'OIPC\', true);commit;') + op.execute('Insert into public."NotificationTypes" (name, description, isactive) values (\'OIPC Due Reminder\', \'OIPC Due Reminder\', true);commit;') + op.execute('Insert into public."CommentTypes" (name, description, isactive) values (\'OIPC Tracking\', \'OIPC Tracking\', true);commit;') + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.execute('delete from public."NotificationTypes" where name in (\'OIPC\');commit;') + op.execute('delete from public."NotificationTypes" where name in (\'OIPC Due Reminder\');commit;') + op.execute('delete from public."CommentTypes" where name in (\'OIPC Tracking\');commit;') + # ### end Alembic commands ### diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index 8abc19dc7..f651e0231 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -788,6 +788,33 @@ def getupcomingdivisionduerecords(cls): finally: db.session.close() return upcomingduerecords + + @classmethod + def getupcomingoipcduerecords(cls): + upcomingduerecords = [] + try: + sql = """select axisrequestid, filenumber, fma.foiministryrequestid , fma.foiministryrequestversion, fma.foirequest_id, + frd.oipcid , frd.inquiryattributes ->> 'orderno'as orderno, + frd.inquiryattributes ->> 'inquirydate' as duedate, frd.created_at, frd.createdby + from "FOIRequestOIPC" frd + inner join (select distinct on (fpa.foiministryrequestid) foiministryrequestid, version as foiministryrequestversion, axisrequestid, filenumber, foirequest_id, requeststatusid + from "FOIMinistryRequests" fpa + order by fpa.foiministryrequestid , fpa.version desc) fma on frd.foiministryrequest_id = fma.foiministryrequestid + and frd.foiministryrequestversion_id = fma.foiministryrequestversion and fma.requeststatusid not in (5,6,4,11,3,15) + and (frd.inquiryattributes ->> 'inquirydate')::date between NOW() - INTERVAL '7 DAY' AND NOW() + INTERVAL '7 DAY' + order by frd.foiministryrequest_id , frd.foiministryrequestversion_id desc;""" + rs = db.session.execute(text(sql)) + for row in rs: + upcomingduerecords.append({"axisrequestid": row["axisrequestid"], "filenumber": row["filenumber"], + "foiministryrequestid": row["foiministryrequestid"], "version": row["foiministryrequestversion"], + "foirequest_id": row["foirequest_id"], "created_at": row["created_at"], "createdby": row["createdby"], + "orderno": row["orderno"],"duedate": row["duedate"]}) + except Exception as ex: + logging.error(ex) + raise ex + finally: + db.session.close() + return upcomingduerecords @classmethod def updateduedate(cls, ministryrequestid, duedate, userid)->DefaultMethodResult: diff --git a/request-management-api/request_api/models/OIPCReviewTypesReasons.py b/request-management-api/request_api/models/OIPCReviewTypesReasons.py index 3fc17e221..32fe9334b 100644 --- a/request-management-api/request_api/models/OIPCReviewTypesReasons.py +++ b/request-management-api/request_api/models/OIPCReviewTypesReasons.py @@ -7,10 +7,10 @@ class OIPCReviewTypesReasons(db.Model): __tablename__ = 'OIPCReviewTypesReasons' # Defining the columns reviewtypereasonid = db.Column(db.Integer, primary_key=True,autoincrement=True) - reviewtypeid = db.Column(db.Integer, ForeignKey('FOIReviewTypes')) - relationship("FOIReviewTypes", backref=backref("FOIReviewTypes"), uselist=False) - reasonid = db.Column(db.Integer, ForeignKey('FOIReasons')) - relationship("FOIReasons", backref=backref("FOIReasons"), uselist=False) + reviewtypeid = db.Column(db.Integer, ForeignKey('OIPCReviewTypes')) + relationship("OIPCReviewTypes", backref=backref("OIPCReviewTypes"), uselist=False) + reasonid = db.Column(db.Integer, ForeignKey('OIPCReasons')) + relationship("OIPCReasons", backref=backref("OIPCReasons"), uselist=False) isactive = db.Column(db.Boolean, unique=False, nullable=False) @classmethod diff --git a/request-management-api/request_api/services/commons/duecalculator.py b/request-management-api/request_api/services/commons/duecalculator.py index d787bda94..c6ecd061e 100644 --- a/request-management-api/request_api/services/commons/duecalculator.py +++ b/request-management-api/request_api/services/commons/duecalculator.py @@ -20,7 +20,13 @@ def getpreviousbusinessday(self, cfrduedate,ca_holidays): return _prevbusinessday else: return self.getpreviousbusinessday(_prevbusinessday,ca_holidays) - + + def getpreviousbusinessday_by_n(self, duedate, ca_holidays, n): + _prevbusinessday = duedate + for i in range(n): + _prevbusinessday = self.getpreviousbusinessday(_prevbusinessday, ca_holidays) + return _prevbusinessday + def formatduedate(self,input): return datetimehandler().formatdate(input) diff --git a/request-management-api/request_api/services/events/oipc.py b/request-management-api/request_api/services/events/oipc.py new file mode 100644 index 000000000..2f6112c0c --- /dev/null +++ b/request-management-api/request_api/services/events/oipc.py @@ -0,0 +1,155 @@ + +from os import stat +from re import VERBOSE +from request_api.models.FOIRequestOIPC import FOIRequestOIPC +from request_api.services.commentservice import commentservice +from request_api.services.oipcservice import oipcservice +from request_api.services.notificationservice import notificationservice +from request_api.models.FOIMinistryRequests import FOIMinistryRequest +import json +from request_api.models.default_method_result import DefaultMethodResult +from enum import Enum +from request_api.exceptions import BusinessException +from dateutil.parser import parse +from request_api.utils.enums import CommentType + +class oipcevent: + """ FOI OIPC Event management service + """ + + def createoipcevent(self, requestid, userid): + inquiryoutcomes = oipcservice().getinquiryoutcomes() + version = FOIMinistryRequest.getversionforrequest(requestid) + curoipcs = FOIRequestOIPC.getoipc(requestid, version) + prevoipcs = FOIRequestOIPC.getoipc(requestid, version[0]-1) + oipcsummary = self.__maintained(curoipcs, prevoipcs, inquiryoutcomes) + if oipcsummary is None or (oipcsummary and len(oipcsummary) <1): + return DefaultMethodResult(True,'No change',requestid) + try: + for oipc in oipcsummary: + self.__createcomment(requestid, oipc, userid) + self.__createnotification(requestid, oipc, userid) + return DefaultMethodResult(True,'Comment posted',requestid) + except BusinessException as exception: + return DefaultMethodResult(False,'unable to post comment - '+exception.message,requestid) + + + def __createcomment(self, requestid, oipc, userid): + comment = {"ministryrequestid": requestid, "comment": self.__preparemessage(oipc)} + commentservice().createministryrequestcomment(comment, userid, CommentType.OIPC.value) + + def __createnotification(self, requestid, oipc, userid): + return notificationservice().createnotification({"message" : self.__preparemessage(oipc)}, requestid, "ministryrequest", "OIPC", userid, False) + + + def __maintained(self,coipcs, poipcs, inquiryoutcomes): + oipcs = [] + for coipc in coipcs: + if self.__isoipcpresent(self.__getoipcnumber(coipc), poipcs) == False: + oipcs.append(self.__createoipcsummary(coipc, EventType.add.value, inquiryoutcomes)) + else: + if self.__isoutcomeclosed(coipc, poipcs) == True: + oipcs.append(self.__createoipcsummary(coipc, EventType.close.value, inquiryoutcomes)) + if self.__isinquirychanged(coipc, poipcs) == True: + oipcs.append(self.__createoipcsummary(coipc, EventType.inquirychange.value, inquiryoutcomes)) + elif self.__isinquiryoutcomechanged(coipc, poipcs, inquiryoutcomes) == True: + oipcs.append(self.__createoipcsummary(coipc, EventType.inquiryoutcome.value, inquiryoutcomes)) + return oipcs + + # def __deleted(self, coipcs, poipcs): + # oipcs = [] + # for poipc in poipcs: + # if self.__isoipcpresent(self.__getoipcnumber(poipc), coipcs) == False: + # oipcs.append(self.__createoipcsummary(poipc, EventType.delete.value)) + # return oipcs + + def __isoipcpresent(self, oipcno, poipcs): + for oipc in poipcs: + if self.__getoipcnumber(oipc) == oipcno: + return True + return False + + def __isoutcomeclosed(self, coipc, poipcs): + for oipc in poipcs: + if self.__getoipcnumber(oipc) == self.__getoipcnumber(coipc) and self.__getoutcome(oipc) != self.__getoutcome(coipc) and self.__getoutcome(coipc) == "Closed": + return True + return False + + def __isinquirychanged(self, coipc, poipcs): + for oipc in poipcs: + if self.__getoipcnumber(oipc) == self.__getoipcnumber(coipc) and self.__getinquiry(oipc) != self.__getinquiry(coipc): + if self.__getinquirycomplydate(coipc) not in (None, "") and self.__getinquiryorderno(coipc) not in (None, "") and (self.__getinquiryorderno(oipc) != self.__getinquiryorderno(coipc) or self.__getinquirycomplydate(oipc) != self.__getinquirycomplydate(coipc)): + return True + return False + + def __isinquiryoutcomechanged(self, coipc, poipcs, inquiryoutcomes): + for oipc in poipcs: + if self.__getoipcnumber(oipc) == self.__getoipcnumber(coipc) and self.__getinquiry(oipc) != self.__getinquiry(coipc): + if self.__getinquiryoutcome(coipc, inquiryoutcomes) not in (None, "") and self.__getinquiryoutcome(oipc, inquiryoutcomes) != self.__getinquiryoutcome(coipc, inquiryoutcomes): + return True + return False + + def __createoipcsummary(self, oipc, event, inquiryoutcomes): + return {'oipcno': self.__getoipcnumber(oipc), + 'reviewtype': self.__getoipcreviewtype(oipc), + 'reason':self.__getreason(oipc), + 'inquirycomplydate': self.__getinquirycomplydate(oipc), + 'inquiryorderno': self.__getinquirycomplydate(oipc), + 'inquiryoutcome': self.__getinquiryoutcome(oipc, inquiryoutcomes), + 'event': event} + + def __getoipcnumber(self, dataschema): + return dataschema['oipcno'] + + def __getoipcreviewtype(self, dataschema): + return dataschema['reviewtype.name'] + + def __getreason(self, dataschema): + return dataschema['reason.name'] + + def __getoutcome(self, dataschema): + return dataschema['outcome.name'] if dataschema['outcomeid'] not in (None,"") else None + + def __getinquirycomplydate(self, dataschema): + return self.__getinquiry(dataschema)['inquirydate'] if dataschema['inquiryattributes'] not in (None,"") else None + + def __getinquiryoutcome(self, dataschema, inquiryoutcomes): + if dataschema['inquiryattributes'] not in (None,""): + inquiryoutcomeid = self.__getinquiry(dataschema)['inquiryoutcome'] + if inquiryoutcomeid not in (None,""): + return self.__getinquiryoutcomename(inquiryoutcomeid, inquiryoutcomes) + return None + + def __getinquiryorderno(self, dataschema): + return self.__getinquiry(dataschema)['orderno'] if dataschema['inquiryattributes'] not in (None,"") else None + + def __getinquiry(self, dataschema): + return dataschema['inquiryattributes'] + + def __getinquiryoutcomename(self, inquiryoutcomeid, inquiryoutcomes): + for outcome in inquiryoutcomes: + if inquiryoutcomeid == outcome["inquiryoutcomeid"]: + return outcome["name"] + return None + + def __preparemessage(self, oipc): + if oipc['event'] == EventType.add.value: + return 'OIPC '+ oipc['reviewtype'] +' opened for '+ oipc['reason'] + elif oipc['event'] == EventType.close.value: + return 'OIPC '+ oipc['reviewtype'] +' closed for '+ oipc['reason'] + elif oipc['event'] == EventType.inquirychange.value: + _inquirychange_msg = 'OIPC Inquiry Order '+ oipc['inquiryorderno'] +' compliance date due '+oipc['inquirycomplydate'] + if oipc['inquiryoutcome'] not in (None, ""): + return _inquirychange_msg+' .Inquiry Decision:' + oipc['inquiryoutcome'] + else: + return _inquirychange_msg + elif oipc['event'] == EventType.inquiryoutcome.value: + return 'OIPC '+ oipc['reviewtype'] +' Inquiry Decision: '+ oipc['inquiryoutcome'] + + +class EventType(Enum): + add = "add" + delete = "delete" + close = "close" + inquirychange = "inquirychange" + inquiryoutcome = "inquiryoutcome" diff --git a/request-management-api/request_api/services/events/oipcduedate.py b/request-management-api/request_api/services/events/oipcduedate.py new file mode 100644 index 000000000..88fbd51b2 --- /dev/null +++ b/request-management-api/request_api/services/events/oipcduedate.py @@ -0,0 +1,69 @@ + +from os import stat +from re import VERBOSE +from request_api.services.commentservice import commentservice +from request_api.services.commons.duecalculator import duecalculator +from request_api.services.notificationservice import notificationservice +from request_api.models.FOIMinistryRequests import FOIMinistryRequest +import json +from request_api.models.default_method_result import DefaultMethodResult +from request_api.exceptions import BusinessException +from dateutil.parser import parse +from flask import current_app + +class oipcduedateevent(duecalculator): + """ FOI OIPC Due Date Event management service + """ + + def createdueevent(self): + try: + _today = self.gettoday() + notificationservice().dismissremindernotification("ministryrequest", self.__notificationtype()) + ca_holidays = self.getholidays() + _upcomingdues = FOIMinistryRequest.getupcomingoipcduerecords() + for entry in _upcomingdues: + _duedate = self.formatduedate(entry['duedate']) + message = None + if _duedate == _today: + message = self.__todayduemessage(entry) + elif self.getpreviousbusinessday(entry['duedate'],ca_holidays) == _today: + message = self.__upcomingduemessage(entry) + elif self.getpreviousbusinessday_by_n(entry['duedate'],ca_holidays, 2) == _today: + message = self.__upcomingduemessage(entry) + self.__createnotification(message,entry['foiministryrequestid']) + self.__createcomment(entry, message) + return DefaultMethodResult(True,'OIPC reminder notifications created',_today) + except BusinessException as exception: + current_app.logger.error("%s,%s" % ('OIPC reminder Notification Error', exception.message)) + return DefaultMethodResult(False,'OIPC reminder notifications failed',_today) + + def __createnotification(self, message, requestid): + if message is not None: + return notificationservice().createnotification({"message" : message}, requestid, "ministryrequest", self.__notificationtype(), self.__defaultuserid(), False) + + def __createcomment(self, entry, message): + if message is not None: + _comment = self.__preparecomment(entry, message) + return commentservice().createcomments(_comment, self.__defaultuserid(), 2) + + + def __preparecomment(self, foirequest, message): + _comment = dict() + _comment['comment'] = message + _comment['ministryrequestid'] = foirequest["foiministryrequestid"] + _comment['version'] = foirequest["version"] + _comment['taggedusers'] = None + _comment['parentcommentid'] = None + return _comment + + def __upcomingduemessage(self, data): + return 'OIPC Inquiry Order '+data['orderno'] +' compliance date due on ' + parse(str(data['duedate'])).strftime("%Y %b %d").upper() + + def __todayduemessage(self, data): + return 'OIPC Inquiry Order '+data['orderno'] +' compliance due Today' + + def __notificationtype(self): + return "OIPC Due Reminder" + + def __defaultuserid(self): + return "System" \ No newline at end of file diff --git a/request-management-api/request_api/services/eventservice.py b/request-management-api/request_api/services/eventservice.py index 9610cb5a6..5e5da210d 100644 --- a/request-management-api/request_api/services/eventservice.py +++ b/request-management-api/request_api/services/eventservice.py @@ -3,12 +3,14 @@ from re import VERBOSE from request_api.services.events.state import stateevent from request_api.services.events.division import divisionevent +from request_api.services.events.oipc import oipcevent from request_api.services.events.assignment import assignmentevent from request_api.services.events.cfrdate import cfrdateevent from request_api.services.events.comment import commentevent from request_api.services.events.watcher import watcherevent from request_api.services.events.legislativedate import legislativedateevent from request_api.services.events.divisiondate import divisiondateevent +from request_api.services.events.oipcduedate import oipcduedateevent from request_api.services.events.extension import extensionevent from request_api.services.events.cfrfeeform import cfrfeeformevent from request_api.services.events.payment import paymentevent @@ -33,8 +35,9 @@ def posteventsync(self, requestid, requesttype, userid, username, isministryuser stateeventresponse = stateevent().createstatetransitionevent(requestid, requesttype, userid, username) divisioneventresponse = divisionevent().createdivisionevent(requestid, requesttype, userid) assignmentresponse = assignmentevent().createassignmentevent(requestid, requesttype, userid, isministryuser,assigneename,username) - if stateeventresponse.success == False or divisioneventresponse.success == False or assignmentresponse.success == False: - current_app.logger.error("FOI Notification failed for event for request= %s ; state response=%s ; division response=%s ; assignment response=%s" % (requestid, stateeventresponse.message, divisioneventresponse.message, assignmentresponse.message)) + oipcresponse = oipcevent().createoipcevent(requestid, userid) + if stateeventresponse.success == False or divisioneventresponse.success == False or assignmentresponse.success == False or oipcresponse.success == False: + current_app.logger.error("FOI Notification failed for event for request= %s ; state response=%s ; division response=%s ; assignment response=%s ; oipc response=%s" % (requestid, stateeventresponse.message, divisioneventresponse.message, assignmentresponse.message, oipcresponse.message)) except BusinessException as exception: self.__logbusinessexception(exception) @@ -60,10 +63,11 @@ def postreminderevent(self): cfreventresponse = cfrdateevent().createdueevent() legislativeeventresponse = legislativedateevent().createdueevent() divisioneventresponse = divisiondateevent().createdueevent() + oipceventresponse = oipcduedateevent().createdueevent() paymentremindereventresponse = paymentevent().createpaymentreminderevent() - section5pendingresponse = section5pendingevent().createdueevent() - if cfreventresponse.success == False or legislativeeventresponse.success == False or divisioneventresponse.success == False or paymentremindereventresponse.success == False or section5pendingresponse == False: - current_app.logger.error("FOI Notification failed for reminder event response=%s ; legislative response=%s ; division response=%s ; payment response=%s ; section5pending response=%s" % (cfreventresponse.message, legislativeeventresponse.message, divisioneventresponse.message, paymentremindereventresponse.message, section5pendingresponse.message)) + section5pendingresponse = section5pendingevent().createdueevent() + if cfreventresponse.success == False or legislativeeventresponse.success == False or divisioneventresponse.success == False or paymentremindereventresponse.success == False or section5pendingresponse == False or oipceventresponse == False: + current_app.logger.error("FOI Notification failed for reminder event response=%s ; legislative response=%s ; division response=%s ; payment response=%s ; section5pending response=%s ; oipcduereminder response=%s" % (cfreventresponse.message, legislativeeventresponse.message, divisioneventresponse.message, paymentremindereventresponse.message, section5pendingresponse.message, oipceventresponse.message)) return DefaultMethodResult(False,'Due reminder notifications failed',cfreventresponse.identifier) return DefaultMethodResult(True,'Due reminder notifications created',cfreventresponse.identifier) except BusinessException as exception: diff --git a/request-management-api/request_api/services/notifications/notificationconfig.py b/request-management-api/request_api/services/notifications/notificationconfig.py index 522ba1749..318f5a536 100644 --- a/request-management-api/request_api/services/notifications/notificationconfig.py +++ b/request-management-api/request_api/services/notifications/notificationconfig.py @@ -43,7 +43,11 @@ def getnotificationtypeid(self, notificationtype): elif notificationtype == "Payment": return 17 elif notificationtype == "Section 5 Pending Reminder": - return 20 + return 20 + elif notificationtype == "OIPC": + return 21 + elif notificationtype == "OIPC Due Reminder": + return 22 return 0 def getnotificationusertypeid(self, notificationusertype): diff --git a/request-management-api/request_api/utils/enums.py b/request-management-api/request_api/utils/enums.py index f21d807ab..2bad91da1 100644 --- a/request-management-api/request_api/utils/enums.py +++ b/request-management-api/request_api/utils/enums.py @@ -132,6 +132,7 @@ class CommentType(Enum): UserComment = 1 SystemGenerated = 2 DivisionStages = 3 + OIPC = 4 class DocumentPathMapperCategory(Enum): Attachments = "Attachments" From 10106ab4d18f0b6ddad15f09454f761bbcdd9fad Mon Sep 17 00:00:00 2001 From: "sumathi.thirumani" Date: Wed, 6 Dec 2023 09:47:44 -0800 Subject: [PATCH 097/238] Changes to fix the finding to include outcome. --- request-management-api/request_api/services/events/oipc.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/request-management-api/request_api/services/events/oipc.py b/request-management-api/request_api/services/events/oipc.py index 2f6112c0c..b32cdd79b 100644 --- a/request-management-api/request_api/services/events/oipc.py +++ b/request-management-api/request_api/services/events/oipc.py @@ -93,6 +93,7 @@ def __createoipcsummary(self, oipc, event, inquiryoutcomes): return {'oipcno': self.__getoipcnumber(oipc), 'reviewtype': self.__getoipcreviewtype(oipc), 'reason':self.__getreason(oipc), + 'outcome': self.__getoutcome(oipc), 'inquirycomplydate': self.__getinquirycomplydate(oipc), 'inquiryorderno': self.__getinquirycomplydate(oipc), 'inquiryoutcome': self.__getinquiryoutcome(oipc, inquiryoutcomes), @@ -136,7 +137,7 @@ def __preparemessage(self, oipc): if oipc['event'] == EventType.add.value: return 'OIPC '+ oipc['reviewtype'] +' opened for '+ oipc['reason'] elif oipc['event'] == EventType.close.value: - return 'OIPC '+ oipc['reviewtype'] +' closed for '+ oipc['reason'] + return 'OIPC '+ oipc['reviewtype'] +' closed for '+ oipc['outcome'] elif oipc['event'] == EventType.inquirychange.value: _inquirychange_msg = 'OIPC Inquiry Order '+ oipc['inquiryorderno'] +' compliance date due '+oipc['inquirycomplydate'] if oipc['inquiryoutcome'] not in (None, ""): From 206b4cd68400dfaf95ad99c2419c8f9b4c14aa80 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Wed, 6 Dec 2023 10:32:22 -0800 Subject: [PATCH 098/238] Verification of minsitry user added to OIPC components + created new oipc component for ministry user view --- .../components/FOI/FOIRequest/FOIRequest.js | 4 + .../FOI/FOIRequest/FOIRequestHeader/index.js | 4 +- .../MinistryReview/MinistryReview.js | 16 ++ .../MinistryReview/RequestHeader.js | 4 +- .../FOI/FOIRequest/OIPCDetails/Index.jsx | 26 ++-- .../OIPCDetails/OIPCDetailsMinistry.jsx | 141 ++++++++++++++++++ .../FOI/customComponents/RequestFlag.js | 4 +- 7 files changed, 185 insertions(+), 14 deletions(-) create mode 100644 forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsMinistry.jsx diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index 2deb1f15f..70711c450 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -939,6 +939,8 @@ const FOIRequest = React.memo(({ userDetail }) => { requestDetails?.requestType === FOI_COMPONENT_CONSTANTS.REQUEST_TYPE_GENERAL) } + console.log("REQ", requestDetails) + return (!isLoading && requestDetails && Object.keys(requestDetails).length !== 0) || @@ -1152,6 +1154,7 @@ const FOIRequest = React.memo(({ userDetail }) => { handlestatusudpate={handlestatusudpate} userDetail={userDetail} disableInput={disableInput} + isMinistry={false} isAddRequest={isAddRequest} handleOipcReviewFlagChange={handleOipcReviewFlagChange} showOipcReviewFlag={requestState.toLowerCase() !== StateEnum.intakeinprogress.name.toLowerCase() && requestState.toLowerCase() !== StateEnum.unopened.name.toLowerCase()} @@ -1277,6 +1280,7 @@ const FOIRequest = React.memo(({ userDetail }) => { updateOIPC={updateOIPC} addOIPC={addOIPC} removeOIPC={removeOIPC} + isMinistry={false} /> )} diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js index 69c3ed18f..ddca6cd7b 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js @@ -53,7 +53,8 @@ const FOIRequestHeader = React.memo( disableInput, isAddRequest, handleOipcReviewFlagChange, - showOipcReviewFlag + showOipcReviewFlag, + isMinistry, }) => { /** * Header of Review request in the UI @@ -296,6 +297,7 @@ const FOIRequestHeader = React.memo( isActive={requestDetails.isoipcreview} handleSelect={handleOipcReviewFlagChange} showFlag={showOipcReviewFlag} + isMinistry={false} /> {/* ({ root: { @@ -235,6 +237,13 @@ const MinistryReview = React.memo(({ userDetail }) => { ); const [unSavedRequest, setUnSavedRequest] = React.useState(false); let ministryassignedtousername = "Unassigned"; + + const userGroups = userDetail?.groups?.map(group => group.slice(1)); + console.log(userGroups) + const isMinistry = isMinistryLogin(userGroups); + console.log(isMinistry) + console.log(requestDetails) + useEffect(() => { const requestDetailsValue = requestDetails; setSaveMinistryRequestObject(requestDetailsValue); @@ -753,6 +762,7 @@ const MinistryReview = React.memo(({ userDetail }) => { setSaveMinistryRequestObject } ministryAssigneeValue={ministryAssignedToValue} + isMinistry={isMinistry} /> @@ -768,6 +778,12 @@ const MinistryReview = React.memo(({ userDetail }) => { /> {divisionsBox} {/* */} + {requestDetails.isoipcreview && requestState && requestState.toLowerCase() !== StateEnum.intakeinprogress.name.toLowerCase() && requestState.toLowerCase() !== StateEnum.unopened.name.toLowerCase() && ( + + )} { const { requestId, ministryId } = useParams(); const _requestDetails = requestDetails; @@ -108,6 +109,7 @@ const RequestHeader = React.memo(({ type="oipcreview" requestDetails={requestDetails} isActive={requestDetails.isoipcreview} + isMinistry={isMinistry} /> {/* { - const { oipcData, addOIPC, removeOIPC, updateOIPC } = props; + const { oipcData, addOIPC, removeOIPC, updateOIPC, isMinistry } = props; //Styling const useStyles = makeStyles({ @@ -30,15 +31,20 @@ const OIPCDetails = (props) => { }> OIPC DETAILS - - -
- -

Add Additional OIPC Complaint

-
-
+ {isMinistry ? + + + : + + +
+ +

Add Additional OIPC Complaint

+
+
+ }
); diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsMinistry.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsMinistry.jsx new file mode 100644 index 000000000..87cd7b14f --- /dev/null +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsMinistry.jsx @@ -0,0 +1,141 @@ +import { TextField, FormControlLabel, Grid, Checkbox, Divider } from '@material-ui/core'; +import './oipcdetails.scss'; + +const OIPCDetailsMinistry = (props) => { + const {oipcData} = props; + + return ( +
+ {oipcData.map((oipc, index) => { + return ( + <> + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+

In Inquiry?

+ } + label="Yes" + /> + } + label="No" + /> +
+
+

In Judicial Review?

+ } + label="Yes" + /> + } + label="No" + /> +
+
+

In Subsequent Appeal?

+ } + label="Yes" + /> + } + label="No" + /> +
+
+ {index !== (oipcData?.length - 1) && } + + ) + })} +
+ ); +} + +export default OIPCDetailsMinistry; \ No newline at end of file diff --git a/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js b/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js index 3899502ec..204c2d506 100644 --- a/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js +++ b/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js @@ -17,7 +17,7 @@ import TextField from "@mui/material/TextField"; //Types are: //oipcreview //phasedrelease -const RequestFlag = ({ isActive, type, handleSelect, showFlag = true }) => { +const RequestFlag = ({ isActive, type, handleSelect, showFlag = true, isMinistry }) => { const [isSelected, setIsSelected] = useState(isActive || false); const [modalOpen, setModalOpen] = useState(false); const [modalHeading, setModalHeading] = useState(""); @@ -186,7 +186,7 @@ const RequestFlag = ({ isActive, type, handleSelect, showFlag = true }) => { onChange={handleValueChange} inputProps={{ "aria-labelledby": "restrict-dropdown-label" }} input={} - disabled={false} + disabled={isMinistry} > {options.map((option) => ( Date: Wed, 6 Dec 2023 11:25:57 -0800 Subject: [PATCH 099/238] Revert to reason. --- request-management-api/request_api/services/events/oipc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/request-management-api/request_api/services/events/oipc.py b/request-management-api/request_api/services/events/oipc.py index b32cdd79b..1742ca1b2 100644 --- a/request-management-api/request_api/services/events/oipc.py +++ b/request-management-api/request_api/services/events/oipc.py @@ -137,7 +137,7 @@ def __preparemessage(self, oipc): if oipc['event'] == EventType.add.value: return 'OIPC '+ oipc['reviewtype'] +' opened for '+ oipc['reason'] elif oipc['event'] == EventType.close.value: - return 'OIPC '+ oipc['reviewtype'] +' closed for '+ oipc['outcome'] + return 'OIPC '+ oipc['reviewtype'] +' closed for '+ oipc['reason'] elif oipc['event'] == EventType.inquirychange.value: _inquirychange_msg = 'OIPC Inquiry Order '+ oipc['inquiryorderno'] +' compliance date due '+oipc['inquirycomplydate'] if oipc['inquiryoutcome'] not in (None, ""): From 107a3a387e924c681362437f4055ad65f699121e Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Wed, 6 Dec 2023 11:48:23 -0800 Subject: [PATCH 100/238] Adjusted labelling for fields --- .../src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index b70d30b71..818845a9f 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -360,7 +360,7 @@ const OIPCItem = (props) => { handleInquiryFields(event.target.value, "COMPLYDATE")} @@ -394,7 +394,7 @@ const OIPCItem = (props) => { onChange = {(event) => handleInquiryFields(event.target.value, "INQUIRYOUTCOME")} fullWidth value={oipc.inquiryattributes.inquiryoutcome ? oipc.inquiryattributes.inquiryoutcome : -1} - label="Outcome" + label="Inquiry Outcome" disabled={oipc.outcomeid && oipc.outcomeid !== 5} > From 0df3d4696152427e09acae7f1f093a40e8a8a08c Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Wed, 6 Dec 2023 14:17:25 -0800 Subject: [PATCH 101/238] Add flags column to IAO advanced search --- .../AdvancedSearch/DataGridAdvancedSearch.js | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/forms-flow-web/src/components/FOI/Dashboard/IAO/AdvancedSearch/DataGridAdvancedSearch.js b/forms-flow-web/src/components/FOI/Dashboard/IAO/AdvancedSearch/DataGridAdvancedSearch.js index 8cd13422e..c5b84c935 100644 --- a/forms-flow-web/src/components/FOI/Dashboard/IAO/AdvancedSearch/DataGridAdvancedSearch.js +++ b/forms-flow-web/src/components/FOI/Dashboard/IAO/AdvancedSearch/DataGridAdvancedSearch.js @@ -12,7 +12,8 @@ import { getReceivedDate, // onBehalfFullName, getRecordsDue, - LightTooltip, + LightTooltip, + displayQueueFlagIcons, } from "../../utils"; import { ActionContext } from "./ActionContext"; import { @@ -97,6 +98,12 @@ const DataGridAdvancedSearch = ({ userDetail }) => { const ProcessingTeamColumns = [ + { + field: "flags", + headerName: "FLAGS", + headerAlign: "left", + renderCell: displayQueueFlagIcons, + }, { field: "axisRequestId", headerName: "ID NUMBER", @@ -189,6 +196,12 @@ const DataGridAdvancedSearch = ({ userDetail }) => { ]; const IntakeTeamColumns = [ + { + field: "flags", + headerName: "FLAGS", + headerAlign: "left", + renderCell: displayQueueFlagIcons, + }, { field: "applicantName", headerName: "APPLICANT NAME", @@ -250,6 +263,12 @@ const DataGridAdvancedSearch = ({ userDetail }) => { ]; const FlexTeamColumns = [ + { + field: "flags", + headerName: "FLAGS", + headerAlign: "left", + renderCell: displayQueueFlagIcons, + }, { field: "axisRequestId", headerName: "ID NUMBER", From 2e1b1199e751678f55a8a9e3a367a16b57c7ae0e Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Wed, 6 Dec 2023 14:51:37 -0800 Subject: [PATCH 102/238] Add requestFlags param to advanced search --- request-management-api/request_api/resources/advancedsearch.py | 1 + request-management-api/request_api/services/dashboardservice.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/request-management-api/request_api/resources/advancedsearch.py b/request-management-api/request_api/resources/advancedsearch.py index 61233e686..ca5cdc130 100644 --- a/request-management-api/request_api/resources/advancedsearch.py +++ b/request-management-api/request_api/resources/advancedsearch.py @@ -43,6 +43,7 @@ def get(): 'requeststate': flask.request.args.getlist('requestState[]'), 'requeststatus': flask.request.args.getlist('requestStatus[]'), 'requesttype': flask.request.args.getlist('requestType[]'), + 'requestflags': flask.request.args.getlist('requestFlags[]'), 'publicbody': flask.request.args.getlist('publicBodies[]'), 'daterangetype': flask.request.args.get('dateRangeType', None, type=str), diff --git a/request-management-api/request_api/services/dashboardservice.py b/request-management-api/request_api/services/dashboardservice.py index 5a89ac3c6..2d69c0525 100644 --- a/request-management-api/request_api/services/dashboardservice.py +++ b/request-management-api/request_api/services/dashboardservice.py @@ -166,7 +166,7 @@ def getministryrequestqueuepagination (self, groups=None, page=1, size=10, sorti return jsonify({'data': requestqueue, 'meta': meta}) - def advancedsearch(self, params={'usertype': 'iao', 'groups':None, 'page':1, 'size':10, 'sortingitems':[], 'sortingorders':[], 'requeststate':[], 'requeststatus':[], 'requesttype':[], 'publicbody':[], 'daterangetype':None, 'fromdate':None, 'todate':None, 'search':None, 'keywords':[], 'userid':None}): + def advancedsearch(self, params={'usertype': 'iao', 'groups':None, 'page':1, 'size':10, 'sortingitems':[], 'sortingorders':[], 'requeststate':[], 'requeststatus':[], 'requesttype':[], 'requestflags':[], 'publicbody':[], 'daterangetype':None, 'fromdate':None, 'todate':None, 'search':None, 'keywords':[], 'userid':None}): userid = AuthHelper.getuserid() if (params['usertype'] == "iao"): From b42f5956ec72804b7425926887c625f8f0fa555c Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Wed, 6 Dec 2023 14:52:27 -0800 Subject: [PATCH 103/238] Add requestFlags filters to FOIMinistryRequest model --- .../request_api/models/FOIMinistryRequests.py | 46 +++++++++++++++++-- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index cb601bd7f..89f7039e7 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -27,6 +27,7 @@ from request_api.utils.enums import StateName from .FOIMinistryRequestSubjectCodes import FOIMinistryRequestSubjectCode from .SubjectCodes import SubjectCode +from .FOIRequestOIPC import FOIRequestOIPC class FOIMinistryRequest(db.Model): # Name of the table in our database @@ -364,7 +365,7 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us if(len(filterfields) > 0 and keyword is not None): filtercondition = [] - if(keyword != "restricted" and keyword.lower() != "oipc"): + if(keyword != "restricted"): for field in filterfields: filtercondition.append(FOIMinistryRequest.findfield(field, iaoassignee, ministryassignee).ilike('%'+keyword+'%')) else: @@ -491,7 +492,8 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us FOIRestrictedMinistryRequest.isrestricted.label('isiaorestricted'), ministry_restricted_requests.isrestricted.label('isministryrestricted'), SubjectCode.name.label('subjectcode'), - FOIMinistryRequest.isoipcreview.label('isoipcreview') + FOIMinistryRequest.isoipcreview.label('isoipcreview'), + FOIRequestOIPC.oipcno.label('oipc_number') ] basequery = _session.query( @@ -562,6 +564,10 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us SubjectCode, SubjectCode.subjectcodeid == FOIMinistryRequestSubjectCode.subjectcodeid, isouter=True + ).join( + FOIRequestOIPC, + and_(FOIRequestOIPC.foiministryrequest_id == FOIMinistryRequest.foiministryrequestid, FOIRequestOIPC.foiministryrequestversion_id == FOIMinistryRequest.version), + isouter=True ).filter(or_(FOIMinistryRequest.requeststatusid != 3, and_(FOIMinistryRequest.isoipcreview == True, FOIMinistryRequest.requeststatusid == 3))) if(additionalfilter == 'watchingRequests'): @@ -668,7 +674,9 @@ def findfield(cls, x, iaoassignee, ministryassignee): 'ministry': func.upper(ProgramArea.bcgovcode), 'requestPageCount': FOIMinistryRequest.requestpagecount, 'closedate': FOIMinistryRequest.closedate, - 'subjectcode': SubjectCode.name + 'subjectcode': SubjectCode.name, + 'isoipcreview': FOIMinistryRequest.isoipcreview, + 'oipc_number': FOIRequestOIPC.oipcno }.get(x, FOIMinistryRequest.axisrequestid) @classmethod @@ -1038,7 +1046,8 @@ def getbasequery(cls, iaoassignee, ministryassignee, userid=None, requestby='IAO FOIRestrictedMinistryRequest.isrestricted.label('isiaorestricted'), ministry_restricted_requests.isrestricted.label('isministryrestricted'), SubjectCode.name.label('subjectcode'), - FOIMinistryRequest.isoipcreview.label('isoipcreview') + FOIMinistryRequest.isoipcreview.label('isoipcreview'), + FOIRequestOIPC.oipcno.label('oipc_number') ] basequery = _session.query( @@ -1109,6 +1118,10 @@ def getbasequery(cls, iaoassignee, ministryassignee, userid=None, requestby='IAO SubjectCode, SubjectCode.subjectcodeid == FOIMinistryRequestSubjectCode.subjectcodeid, isouter=True + ).join( + FOIRequestOIPC, + and_(FOIRequestOIPC.foiministryrequest_id == FOIMinistryRequest.foiministryrequestid, FOIRequestOIPC.foiministryrequestversion_id == FOIMinistryRequest.version), + isouter=True ) if(isiaorestrictedfilemanager == True or isministryrestrictedfilemanager == True): @@ -1200,6 +1213,11 @@ def getfilterforadvancedsearch(cls, params, iaoassignee, ministryassignee): requesttypecondition = FOIMinistryRequest.getfilterforrequesttype(params, iaoassignee, ministryassignee) filtercondition.append(requesttypecondition) + #request flags: restricted, oipc, phased + if(len(params['requestflags']) > 0): + requestflagscondition = FOIMinistryRequest.getfilterforrequestflags(params, iaoassignee, ministryassignee) + filtercondition.append(requestflagscondition) + #public body: EDUC, etc. if(len(params['publicbody']) > 0): publicbodycondition = FOIMinistryRequest.getfilterforpublicbody(params, iaoassignee, ministryassignee) @@ -1246,6 +1264,26 @@ def getfilterforrequesttype(cls, params, iaoassignee, ministryassignee): requesttypecondition.append(FOIMinistryRequest.findfield('requestType', iaoassignee, ministryassignee) == type) return or_(*requesttypecondition) + @classmethod + def getfilterforrequestflags(cls, params, iaoassignee, ministryassignee): + #request flags: restricted, oipc, phased + requestflagscondition = [] + #alias for getting ministry restricted flag from FOIRestrictedMinistryRequest + ministry_restricted_requests = aliased(FOIRestrictedMinistryRequest) + + for flag in params['requestflags']: + if (flag.lower() == 'restricted'): + if(iaoassignee): + requestflagscondition.append(FOIRestrictedMinistryRequest.isrestricted == True) + elif (ministryassignee): + requestflagscondition.append(ministry_restricted_requests.isrestricted == True) + if (flag.lower() == 'oipc'): + requestflagscondition.append(FOIMinistryRequest.findfield('isoipcreview', iaoassignee, ministryassignee) == True) + if (flag.lower() == 'phased'): + # requestflagscondition.append(FOIMinistryRequest.findfield('isphasedrelease', iaoassignee, ministryassignee) == True) + continue + return or_(*requestflagscondition) + @classmethod def getfilterforpublicbody(cls, params, iaoassignee, ministryassignee): #public body: EDUC, etc. From 78826f91254d029a4e5eb65fd216f2d9fbf89a5d Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Wed, 6 Dec 2023 14:53:15 -0800 Subject: [PATCH 104/238] Add requestFlags to advanced search service and enums --- .../src/apiManager/services/FOI/foiAdvancedSearchServices.js | 2 ++ .../src/components/FOI/Dashboard/IAO/AdvancedSearch/enum.js | 1 + .../components/FOI/Dashboard/Ministry/AdvancedSearch/enum.js | 1 + 3 files changed, 4 insertions(+) diff --git a/forms-flow-web/src/apiManager/services/FOI/foiAdvancedSearchServices.js b/forms-flow-web/src/apiManager/services/FOI/foiAdvancedSearchServices.js index cbb9fc669..e7fb181d5 100644 --- a/forms-flow-web/src/apiManager/services/FOI/foiAdvancedSearchServices.js +++ b/forms-flow-web/src/apiManager/services/FOI/foiAdvancedSearchServices.js @@ -13,6 +13,7 @@ export const fetchAdvancedSearchData = ({ requestState = [], requestStatus = [], requestType = [], + requestFlags = [], dateRangeType = null, fromDate = null, toDate = null, @@ -41,6 +42,7 @@ export const fetchAdvancedSearchData = ({ requestState: requestState, requestStatus: requestStatus, requestType: requestType, + requestFlags: requestFlags, dateRangeType: dateRangeType, fromDate: fromDate, toDate: toDate, diff --git a/forms-flow-web/src/components/FOI/Dashboard/IAO/AdvancedSearch/enum.js b/forms-flow-web/src/components/FOI/Dashboard/IAO/AdvancedSearch/enum.js index ad08f9752..ee6686a63 100644 --- a/forms-flow-web/src/components/FOI/Dashboard/IAO/AdvancedSearch/enum.js +++ b/forms-flow-web/src/components/FOI/Dashboard/IAO/AdvancedSearch/enum.js @@ -6,6 +6,7 @@ const SearchFilter = Object.freeze({ APPLICANT_NAME: "applicantname", ASSIGNEE_NAME: "assigneename", SUBJECT_CODE: "subjectcode", + OIPC_NUMBER: "oipc_number" }); const DateRangeTypes = Object.freeze([ diff --git a/forms-flow-web/src/components/FOI/Dashboard/Ministry/AdvancedSearch/enum.js b/forms-flow-web/src/components/FOI/Dashboard/Ministry/AdvancedSearch/enum.js index 95a4f8ca8..4afb63782 100644 --- a/forms-flow-web/src/components/FOI/Dashboard/Ministry/AdvancedSearch/enum.js +++ b/forms-flow-web/src/components/FOI/Dashboard/Ministry/AdvancedSearch/enum.js @@ -6,6 +6,7 @@ const SearchFilter = Object.freeze({ APPLICANT_NAME: "applicantname", ASSIGNEE_NAME: "ministryassigneename", SUBJECT_CODE: "subjectcode", + OIPC_NUMBER: "oipc_number" }); const DateRangeTypes = Object.freeze([ From c8a7c5bd9a84e370a075d81126bcc9321a36ec3a Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Wed, 6 Dec 2023 14:58:35 -0800 Subject: [PATCH 105/238] Add OIPC number filter and request flags column to advanced search --- .../IAO/AdvancedSearch/SearchComponent.js | 220 ++++++++++++----- .../AdvancedSearch/SearchComponent.js | 222 +++++++++++++----- 2 files changed, 315 insertions(+), 127 deletions(-) diff --git a/forms-flow-web/src/components/FOI/Dashboard/IAO/AdvancedSearch/SearchComponent.js b/forms-flow-web/src/components/FOI/Dashboard/IAO/AdvancedSearch/SearchComponent.js index 56c04bd31..5983654d2 100644 --- a/forms-flow-web/src/components/FOI/Dashboard/IAO/AdvancedSearch/SearchComponent.js +++ b/forms-flow-web/src/components/FOI/Dashboard/IAO/AdvancedSearch/SearchComponent.js @@ -100,12 +100,12 @@ const AdvancedSearch = ({ userDetail }) => { const tooltipContentRight = { "title": "Advanced Search", - "content": "To conduct an Advanced Search using one of the six filter buttons, you must also enter one or more key words." + "content": "To conduct an Advanced Search using one of the seven filter buttons, you must also enter one or more key words." }; const tooltipContentLeft = { "title": "Advanced Search", - "content": "Use one or more fields from the following sections on their own or to narrow your search: Request State/Status/Type, Date Range, or Public Body." + "content": "Use one or more fields from the following sections on their own or to narrow your search: Request State/Status/Type/Flags, Date Range, or Public Body." }; @@ -181,6 +181,23 @@ const AdvancedSearch = ({ userDetail }) => { } }); + const initialRequestFlags = { + restricted: false, + oipc: false, + phased: false + }; + const [requestFlags, setRequestFlags] = useState(() => { + if (Object.keys(advancedSearchParams).length > 0 && advancedSearchParams.requestFlags.length > 0) { + let savedRequestFlags = {...initialRequestFlags} + advancedSearchParams.requestFlags.forEach(type => { + savedRequestFlags[type] = true; + }); + return savedRequestFlags; + } else { + return initialRequestFlags; + } + }); + const [selectedDateRangeType, setSelectedDateRangeType] = useState(advancedSearchParams?.dateRangeType || ""); const [fromDate, setFromDate] = useState(advancedSearchParams?.fromDate || ""); const [toDate, setToDate] = useState(advancedSearchParams?.toDate || ""); @@ -233,6 +250,7 @@ const AdvancedSearch = ({ userDetail }) => { keywords: keywordsMode ? keywords : [searchText.trim()], requestState: getTrueKeysFromCheckboxObject(requestState), requestType: getTrueKeysFromCheckboxObject(requestTypes), + requestFlags: getTrueKeysFromCheckboxObject(requestFlags), requestStatus: getTrueKeysFromCheckboxObject(requestStatus), dateRangeType: selectedDateRangeType || null, fromDate: fromDate || null, @@ -258,6 +276,7 @@ const AdvancedSearch = ({ userDetail }) => { const noSearchCriteria = () => { let selectedRequestStates = getTrueKeysFromCheckboxObject(requestState); let selectedRequestTypes = getTrueKeysFromCheckboxObject(requestTypes); + let selectedRequestFlags = getTrueKeysFromCheckboxObject(requestFlags); let selectedRequestStatus = getTrueKeysFromCheckboxObject(requestStatus); return ((keywords.length===0 && keywordsMode) || (!searchText && !keywordsMode)) && !fromDate @@ -265,6 +284,7 @@ const AdvancedSearch = ({ userDetail }) => { && selectedPublicBodies.length===0 && selectedRequestStates.length===0 && selectedRequestTypes.length===0 + && selectedRequestFlags.length===0 && selectedRequestStatus.length===0; }; @@ -275,6 +295,7 @@ const AdvancedSearch = ({ userDetail }) => { setSearchFilterSelected(); setRequestState(intitialRequestState); setRequestTypes(initialRequestTypes); + setRequestFlags(initialRequestFlags); setRequestStatus(intitialRequestStatus); setFromDate(""); setToDate(""); @@ -323,6 +344,13 @@ const AdvancedSearch = ({ userDetail }) => { }); }; + const handleRequestFlagsChange = (event) => { + setRequestFlags({ + ...requestFlags, + [event.target.name]: event.target.checked, + }); + }; + const handleSelectedDateRangeTypeChange = (event) => { const type = event.target.value; setSelectedDateRangeType(type); @@ -491,73 +519,84 @@ const AdvancedSearch = ({ userDetail }) => { Filter by + + + + clickSearchFilter(SearchFilter.REQUEST_DESCRIPTION) + } + clicked={ + searchFilterSelected === SearchFilter.REQUEST_DESCRIPTION + } + /> + - - - clickSearchFilter(SearchFilter.REQUEST_DESCRIPTION) - } - clicked={ - searchFilterSelected === SearchFilter.REQUEST_DESCRIPTION - } - /> - + + clickSearchFilter(SearchFilter.ID_NUM)} + clicked={searchFilterSelected === SearchFilter.ID_NUM} + /> + - - clickSearchFilter(SearchFilter.ID_NUM)} - clicked={searchFilterSelected === SearchFilter.ID_NUM} - /> - + + + clickSearchFilter(SearchFilter.AXIS_REQUEST_NUM) + } + clicked={ + searchFilterSelected === SearchFilter.AXIS_REQUEST_NUM + } + /> + - - - clickSearchFilter(SearchFilter.AXIS_REQUEST_NUM) - } - clicked={ - searchFilterSelected === SearchFilter.AXIS_REQUEST_NUM - } - /> - + + clickSearchFilter(SearchFilter.APPLICANT_NAME)} + clicked={searchFilterSelected === SearchFilter.APPLICANT_NAME} + /> + - - clickSearchFilter(SearchFilter.APPLICANT_NAME)} - clicked={searchFilterSelected === SearchFilter.APPLICANT_NAME} - /> - + + clickSearchFilter(SearchFilter.ASSIGNEE_NAME)} + clicked={searchFilterSelected === SearchFilter.ASSIGNEE_NAME} + /> + - - clickSearchFilter(SearchFilter.ASSIGNEE_NAME)} - clicked={searchFilterSelected === SearchFilter.ASSIGNEE_NAME} - /> - + + clickSearchFilter(SearchFilter.SUBJECT_CODE)} + clicked={searchFilterSelected === SearchFilter.SUBJECT_CODE} + /> + - - clickSearchFilter(SearchFilter.SUBJECT_CODE)} - clicked={searchFilterSelected === SearchFilter.SUBJECT_CODE} - /> + + clickSearchFilter(SearchFilter.OIPC_NUMBER)} + clicked={searchFilterSelected === SearchFilter.OIPC_NUMBER} + /> + @@ -731,6 +770,61 @@ const AdvancedSearch = ({ userDetail }) => { /> + + + + Request Flags + + + + + + + } + label="Restricted" + /> + + } + label="OIPC" + /> + + } + label="Phased" + /> + + diff --git a/forms-flow-web/src/components/FOI/Dashboard/Ministry/AdvancedSearch/SearchComponent.js b/forms-flow-web/src/components/FOI/Dashboard/Ministry/AdvancedSearch/SearchComponent.js index 68f82525b..19ea4c5b6 100644 --- a/forms-flow-web/src/components/FOI/Dashboard/Ministry/AdvancedSearch/SearchComponent.js +++ b/forms-flow-web/src/components/FOI/Dashboard/Ministry/AdvancedSearch/SearchComponent.js @@ -100,12 +100,12 @@ const AdvancedSearch = ({ userDetail }) => { const tooltipContentRight = { "title": "Advanced Search", - "content": "To conduct an Advanced Search using one of the six filter buttons, you must also enter one or more key words." + "content": "To conduct an Advanced Search using one of the seven filter buttons, you must also enter one or more key words." }; const tooltipContentLeft = { "title": "Advanced Search", - "content": "Use one or more fields from the following sections on their own or to narrow your search: Request State/Status/Type, Date Range, or Public Body." + "content": "Use one or more fields from the following sections on their own or to narrow your search: Request State/Status/Type/Flags, Date Range, or Public Body." }; const [searchFilterSelected, setSearchFilterSelected] = useState(advancedSearchParams?.search || null); @@ -183,6 +183,23 @@ const AdvancedSearch = ({ userDetail }) => { return initialRequestTypes; } }); + + const initialRequestFlags = { + restricted: false, + oipc: false, + phased: false + }; + const [requestFlags, setRequestFlags] = useState(() => { + if (Object.keys(advancedSearchParams).length > 0 && advancedSearchParams.requestFlags.length > 0) { + let savedRequestFlags = {...initialRequestFlags} + advancedSearchParams.requestFlags.forEach(type => { + savedRequestFlags[type] = true; + }); + return savedRequestFlags; + } else { + return initialRequestFlags; + } + }); const [selectedDateRangeType, setSelectedDateRangeType] = useState(advancedSearchParams?.dateRangeType || ""); const [fromDate, setFromDate] = useState(advancedSearchParams?.fromDate || ""); const [toDate, setToDate] = useState(advancedSearchParams?.toDate || ""); @@ -234,6 +251,7 @@ const AdvancedSearch = ({ userDetail }) => { keywords: keywordsMode ? keywords : [searchText.trim()], requestState: getTrueKeysFromCheckboxObject(requestState), requestType: getTrueKeysFromCheckboxObject(requestTypes), + requestFlags: getTrueKeysFromCheckboxObject(requestFlags), requestStatus: getTrueKeysFromCheckboxObject(requestStatus), dateRangeType: selectedDateRangeType || null, fromDate: fromDate || null, @@ -259,6 +277,7 @@ const AdvancedSearch = ({ userDetail }) => { const noSearchCriteria = () => { let selectedRequestStates = getTrueKeysFromCheckboxObject(requestState); let selectedRequestTypes = getTrueKeysFromCheckboxObject(requestTypes); + let selectedRequestFlags = getTrueKeysFromCheckboxObject(requestFlags); let selectedRequestStatus = getTrueKeysFromCheckboxObject(requestStatus); return ((keywords.length===0 && keywordsMode) || (!searchText && !keywordsMode)) && !fromDate @@ -266,6 +285,7 @@ const AdvancedSearch = ({ userDetail }) => { && selectedPublicBodies.length===0 && selectedRequestStates.length===0 && selectedRequestTypes.length===0 + && selectedRequestFlags.length===0 && selectedRequestStatus.length===0; }; @@ -276,6 +296,7 @@ const AdvancedSearch = ({ userDetail }) => { setSearchFilterSelected(); setRequestState(intitialRequestState); setRequestTypes(initialRequestTypes); + setRequestFlags(initialRequestFlags); setRequestStatus(intitialRequestStatus); setFromDate(""); setToDate(""); @@ -336,6 +357,13 @@ const AdvancedSearch = ({ userDetail }) => { }); }; + const handleRequestFlagsChange = (event) => { + setRequestFlags({ + ...requestFlags, + [event.target.name]: event.target.checked, + }); + }; + const handleSelectedDateRangeTypeChange = (event) => { const type = event.target.value; setSelectedDateRangeType(type); @@ -504,73 +532,84 @@ const AdvancedSearch = ({ userDetail }) => { Filter by + + + + clickSearchFilter(SearchFilter.REQUEST_DESCRIPTION) + } + clicked={ + searchFilterSelected === SearchFilter.REQUEST_DESCRIPTION + } + /> + - - - clickSearchFilter(SearchFilter.REQUEST_DESCRIPTION) - } - clicked={ - searchFilterSelected === SearchFilter.REQUEST_DESCRIPTION - } - /> - - - - clickSearchFilter(SearchFilter.ID_NUM)} - clicked={searchFilterSelected === SearchFilter.ID_NUM} - /> - + + clickSearchFilter(SearchFilter.ID_NUM)} + clicked={searchFilterSelected === SearchFilter.ID_NUM} + /> + - - - clickSearchFilter(SearchFilter.AXIS_REQUEST_NUM) - } - clicked={ - searchFilterSelected === SearchFilter.AXIS_REQUEST_NUM - } - /> - + + + clickSearchFilter(SearchFilter.AXIS_REQUEST_NUM) + } + clicked={ + searchFilterSelected === SearchFilter.AXIS_REQUEST_NUM + } + /> + - - clickSearchFilter(SearchFilter.APPLICANT_NAME)} - clicked={searchFilterSelected === SearchFilter.APPLICANT_NAME} - /> - + + clickSearchFilter(SearchFilter.APPLICANT_NAME)} + clicked={searchFilterSelected === SearchFilter.APPLICANT_NAME} + /> + - - clickSearchFilter(SearchFilter.ASSIGNEE_NAME)} - clicked={searchFilterSelected === SearchFilter.ASSIGNEE_NAME} - /> - + + clickSearchFilter(SearchFilter.ASSIGNEE_NAME)} + clicked={searchFilterSelected === SearchFilter.ASSIGNEE_NAME} + /> + - - clickSearchFilter(SearchFilter.SUBJECT_CODE)} - clicked={searchFilterSelected === SearchFilter.SUBJECT_CODE} - /> + + clickSearchFilter(SearchFilter.SUBJECT_CODE)} + clicked={searchFilterSelected === SearchFilter.SUBJECT_CODE} + /> + + + + clickSearchFilter(SearchFilter.OIPC_NUMBER)} + clicked={searchFilterSelected === SearchFilter.OIPC_NUMBER} + /> + @@ -733,6 +772,61 @@ const AdvancedSearch = ({ userDetail }) => { /> + + + + Request Flags + + + + + + + } + label="Restricted" + /> + + } + label="OIPC" + /> + + } + label="Phased" + /> + + From 6ea765b17ba0e6dd00f3ba2d2abb1afc7e00edee Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Wed, 6 Dec 2023 15:52:54 -0800 Subject: [PATCH 106/238] Ticket AC's completed. WIP final stytling + testing --- .../MinistryReview/MinistryReview.js | 5 +- .../FOI/FOIRequest/OIPCDetails/Index.jsx | 38 +-- .../OIPCDetails/OIPCDetailsMinistry.jsx | 253 +++++++++--------- .../FOIRequest/OIPCDetails/oipcdetails.scss | 4 +- 4 files changed, 154 insertions(+), 146 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js index ecc0d588a..d3b9cccdf 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js @@ -239,11 +239,8 @@ const MinistryReview = React.memo(({ userDetail }) => { let ministryassignedtousername = "Unassigned"; const userGroups = userDetail?.groups?.map(group => group.slice(1)); - console.log(userGroups) const isMinistry = isMinistryLogin(userGroups); - console.log(isMinistry) - console.log(requestDetails) - + useEffect(() => { const requestDetailsValue = requestDetails; setSaveMinistryRequestObject(requestDetailsValue); diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx index 842ded558..438443cd8 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx @@ -26,27 +26,27 @@ const OIPCDetails = (props) => { const classes = useStyles(); return ( -
+ <> + {isMinistry ? + : +
- }> - OIPC DETAILS - - {isMinistry ? - - - : - - -
- -

Add Additional OIPC Complaint

-
-
- } + }> + OIPC DETAILS + + + +
+ +

Add Additional OIPC Complaint

+
+
-
+
+ } + ); } diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsMinistry.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsMinistry.jsx index 87cd7b14f..c77e08f1a 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsMinistry.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsMinistry.jsx @@ -1,140 +1,151 @@ -import { TextField, FormControlLabel, Grid, Checkbox, Divider } from '@material-ui/core'; +import { Divider, Card, CardContent } from '@material-ui/core'; import './oipcdetails.scss'; const OIPCDetailsMinistry = (props) => { const {oipcData} = props; return ( -
+ + + {oipcData.map((oipc, index) => { return ( <> - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-

In Inquiry?

- } - label="Yes" - /> - } - label="No" - /> +
+ +
+
+ Order No +
+
+ {oipc.oipcno} +
+
+ +
+
+ Received Date +
+
+ {oipc.receiveddate} +
+
+ +
+
+ Review Type +
+
+ {oipc.reviewetype} +
+
+ +
+
+ Reason +
+
+ {oipc.reason} +
+
+ +
+
+ Status +
+
+ {oipc.status} +
+
+ +
+
+ Investigator/Adjudicator +
+
+ {oipc.investigator ? oipc.investigator : "N/A"} +
+
+ +
+
+ Outcome +
+
+ {oipc.outcome ? oipc.outcome : "N/A"} +
+
+ +
+
+ Closed Date +
+
+ {oipc.closedate ? oipc.closedate : "N/A"} +
+
+ +
+
+ In Inquiry? +
+
+ {oipc.isinquiry ? "Yes" : "No"} +
+
+ +
+
+ In Judical Review? +
+
+ {oipc.isjudicialreview ? "Yes" : "No"} +
+
+ +
+
+ In Subsequent Appeal? +
+
+ {oipc.issubsequentappeal ? "Yes" : "No"} +
+
+
+ {oipc.inquiryattributes && +
+
+
+ Order Comply Date +
+
+ {oipc.inquiryattributes.inquirydate ? oipc.inquiryattributes.inquirydate : "N/A"} +
-
-

In Judicial Review?

- } - label="Yes" - /> - } - label="No" - /> +
+
+ Order No +
+
+ {oipc.inquiryattributes.orderno ? oipc.inquiryattributes.orderno : "N/A"} +
-
-

In Subsequent Appeal?

- } - label="Yes" - /> - } - label="No" - /> +
+
+ Inquiry Outcome +
+
+ {oipc.inquiryattributes.inquiryoutcome ? oipc.inquiryattributes.inquiryoutcome : "N/A"} +
- {index !== (oipcData?.length - 1) && } + } + {index !== (oipcData?.length - 1) && } ) })} -
+ + ); } diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcdetails.scss b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcdetails.scss index 9d467ac10..d28779da2 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcdetails.scss +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcdetails.scss @@ -32,7 +32,7 @@ } .MuiDivider-root { - margin: 10px 0px 16px 0px; - height: 1.5px; + margin: 10px 0px 16px 0px !important; + height: 1.5px !important; } \ No newline at end of file From e0d2aed36ff26e1eedc78387ae63625a142ea04d Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Thu, 7 Dec 2023 10:14:06 -0800 Subject: [PATCH 107/238] Fix iao requestflags search --- .../request_api/models/FOIRawRequests.py | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/request-management-api/request_api/models/FOIRawRequests.py b/request-management-api/request_api/models/FOIRawRequests.py index cedb898b5..6c2ea1eed 100644 --- a/request-management-api/request_api/models/FOIRawRequests.py +++ b/request-management-api/request_api/models/FOIRawRequests.py @@ -571,7 +571,8 @@ def getbasequery(cls, additionalfilter=None, userid=None, isiaorestrictedfileman isiaorestricted, literal(None).label('isministryrestricted'), subjectcode, - literal(None).label('isoipcreview') + literal(None).label('isoipcreview'), + literal(None).label('oipc_number') ] basequery = _session.query(*selectedcolumns).join(subquery_maxversion, and_(*joincondition)).join(FOIAssignee, FOIAssignee.username == FOIRawRequest.assignedto, isouter=True) @@ -790,6 +791,11 @@ def getfilterforadvancedsearch(cls, params): if(len(params['requesttype']) > 0): requesttypecondition = FOIRawRequest.getfilterforrequesttype(params) filtercondition.append(or_(*requesttypecondition)) + + #request flags: restricted, oipc, phased + if(len(params['requestflags']) > 0): + requestflagscondition = FOIRawRequest.getfilterforrequestflags(params) + filtercondition.append(or_(*requestflagscondition)) #public body: EDUC, etc. if(len(params['publicbody']) > 0): @@ -870,6 +876,20 @@ def getfilterforrequesttype(cls, params): return or_(*requesttypecondition) + @classmethod + def getfilterforrequestflags(cls, params): + # this search will be done by the ministry union, so returns filter with no results + requestflagscondition = [] + for flag in params['requestflags']: + if (flag.lower() == 'restricted'): # no results for raw restricted + requestflagscondition.append(FOIRawRequest.findfield('axisRequestId') == 'thisismeanttoreturnafilterconditionwith0results') + if (flag.lower() == 'oipc'): # no results for raw oipc + requestflagscondition.append(FOIRawRequest.findfield('axisRequestId') == 'thisismeanttoreturnafilterconditionwith0results') + if (flag.lower() == 'phased'): + # requestflagscondition.append(FOIMinistryRequest.findfield('isphasedrelease', iaoassignee, ministryassignee) == True) + continue + return requestflagscondition + @classmethod def getfilterforpublicbody(cls, params): #public body: EDUC, etc. From a0b11c6db2e9eab73bee39e0c2016dbffcdc62ec Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Thu, 7 Dec 2023 15:58:03 -0800 Subject: [PATCH 108/238] Adjusted backend endpoint for FOIMINITRIY requests that is reached when assignees are assined. This endpoint now consumes and updates oipc details (and versions) when foi ministry request versions change --- .../components/FOI/FOIRequest/FOIRequest.js | 1 - .../requestserviceministrybuilder.py | 33 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index 70711c450..96c37d40a 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -939,7 +939,6 @@ const FOIRequest = React.memo(({ userDetail }) => { requestDetails?.requestType === FOI_COMPONENT_CONSTANTS.REQUEST_TYPE_GENERAL) } - console.log("REQ", requestDetails) return (!isLoading && requestDetails && diff --git a/request-management-api/request_api/services/foirequest/requestserviceministrybuilder.py b/request-management-api/request_api/services/foirequest/requestserviceministrybuilder.py index f35af8e74..fca98fa3b 100644 --- a/request-management-api/request_api/services/foirequest/requestserviceministrybuilder.py +++ b/request-management-api/request_api/services/foirequest/requestserviceministrybuilder.py @@ -11,6 +11,7 @@ from request_api.models.FOIRequestExtensionDocumentMappings import FOIRequestExtensionDocumentMapping from request_api.models.FOIAssignees import FOIAssignee from request_api.models.FOIMinistryRequestSubjectCodes import FOIMinistryRequestSubjectCode +from request_api.models.FOIRequestOIPC import FOIRequestOIPC from request_api.services.foirequest.requestserviceconfigurator import requestserviceconfigurator from datetime import datetime as datetime2 @@ -86,6 +87,8 @@ def createfoiministryrequestfromobject(self, ministryschema, requestschema, user foiministryrequest.subjectcode = self.__createministrysubjectcode(requestschema, ministryschema["foiministryrequestid"], ministryschema["version"], userid) foiministryrequest.closedate = requestdict['closedate'] foiministryrequest.closereasonid = requestdict['closereasonid'] + foiministryrequest.isoipcreview = ministryschema["isoipcreview"] + foiministryrequest.oipcreviews = self.createfoirequestoipcs(foiministryrequest.isoipcreview, ministryschema["foirequest_id"], ministryschema["version"], userid) return foiministryrequest def __createministrydivisions(self, requestschema, foiministryrequestid, foiministryrequestversion, userid): @@ -309,3 +312,33 @@ def createfoirequestdivision(self, requestschema, requestid, version, userid): def createfoiassigneefromobject(self, username, firstname, middlename, lastname): return FOIAssignee.saveassignee(username, firstname, middlename, lastname) + + def createfoirequestoipcs(self, isoipcreview, requestid, version, userid): + current_oipcs = FOIRequestOIPC.getoipc(requestid, version) + if (isoipcreview == True): + updated_oipcs = [] + for oipc in current_oipcs: + oipcreview = FOIRequestOIPC() + oipcreview.foiministryrequest_id = requestid + oipcreview.foiministryrequestversion_id = version + 1 + oipcreview.oipcno = oipc["oipcno"] + oipcreview.reviewtypeid = oipc["reviewtypeid"] + oipcreview.reasonid = oipc["reasonid"] + oipcreview.statusid = oipc["statusid"] + oipcreview.outcomeid = oipc["outcomeid"] + oipcreview.investigator = oipc["investigator"] if oipc["investigator"] not in (None, "") else None + oipcreview.isinquiry = oipc["isinquiry"] + oipcreview.isjudicialreview = oipc["isjudicialreview"] + oipcreview.issubsequentappeal = oipc["issubsequentappeal"] + oipcreview.issubsequentappeal = oipc["issubsequentappeal"] + oipcreview.receiveddate = oipc["receiveddate"] if oipc["receiveddate"] not in (None, "") else None + oipcreview.closeddate = oipc["closeddate"] if oipc["closeddate"] not in (None, "") else None + oipcreview.isactive = True + if oipc["isinquiry"] == True: + oipcreview.inquiryattributes = oipc["inquiryattributes"] + oipcreview.createdby=userid + oipcreview.created_at= datetime2.now().isoformat() + + updated_oipcs.append(oipcreview) + return updated_oipcs + return [] From 830a95fb32c513ab0240dd654ad2b489659aa1f9 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Fri, 8 Dec 2023 11:30:28 -0800 Subject: [PATCH 109/238] Styling adjusted --- .../OIPCDetails/OIPCDetailsMinistry.jsx | 37 +++++++++---------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsMinistry.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsMinistry.jsx index c77e08f1a..9ff9cad4a 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsMinistry.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsMinistry.jsx @@ -96,50 +96,49 @@ const OIPCDetailsMinistry = (props) => {
- In Judical Review? -
+ Inquiry Order Comply Date +
- {oipc.isjudicialreview ? "Yes" : "No"} + {oipc.inquiryattributes?.inquirydate ? oipc.inquiryattributes.inquirydate : "N/A"}
- In Subsequent Appeal? -
+ Inquiry Order No +
- {oipc.issubsequentappeal ? "Yes" : "No"} + {oipc.inquiryattributes?.orderno ? oipc.inquiryattributes.orderno : "N/A"}
-
- {oipc.inquiryattributes && -
+
- Order Comply Date + Inquiry Outcome
- {oipc.inquiryattributes.inquirydate ? oipc.inquiryattributes.inquirydate : "N/A"} + {oipc.inquiryattributes?.inquiryoutcome ? oipc.inquiryattributes.inquiryoutcome : "N/A"}
+
- Order No -
+ In Judical Review? +
- {oipc.inquiryattributes.orderno ? oipc.inquiryattributes.orderno : "N/A"} + {oipc.isjudicialreview ? "Yes" : "No"}
+
- Inquiry Outcome -
+ In Subsequent Appeal? +
- {oipc.inquiryattributes.inquiryoutcome ? oipc.inquiryattributes.inquiryoutcome : "N/A"} + {oipc.issubsequentappeal ? "Yes" : "No"}
-
- } +
{index !== (oipcData?.length - 1) && } ) From 01c375edd5ed837ed61e26b20df0c8495356bfee Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Fri, 8 Dec 2023 12:14:11 -0800 Subject: [PATCH 110/238] Heading label changed --- .../FOI/FOIRequest/OIPCDetails/OIPCDetailsMinistry.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsMinistry.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsMinistry.jsx index 9ff9cad4a..0c8ee81c0 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsMinistry.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsMinistry.jsx @@ -6,7 +6,7 @@ const OIPCDetailsMinistry = (props) => { return ( - + {oipcData.map((oipc, index) => { return ( From f1b0f8c694ba932e17c8e449e0224e1d8a3f9e3d Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Fri, 8 Dec 2023 13:44:24 -0800 Subject: [PATCH 111/238] Removal of uneeded code from OIPC Components in FE. Code Refactor --- .../FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 21 ++----------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index 818845a9f..f175e9710 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -24,24 +24,6 @@ const OIPCItem = (props) => { const [showAmendModal, setShowAmendModal] = useState(false); //Functions - const generateNamesFromOIPCId = (oipcObj) => { - const reviewtype = oipcReviewtypes.find(reviewtype => reviewtype.reviewtypeid === oipcObj.reviewtypeid && reviewtype.reasonid === oipcObj.reasonid); - const status = oipcStatuses.find(status => status.statusid === oipcObj.statusid); - const outcome = oipcOutcomes.find(outcome => outcome.outcomeid === oipcObj.outcomeid); - - setOipc((prev) => { - return {...prev, reviewtypeName: reviewtype ? reviewtype.type_name : ""} - }) - setOipc((prev) => { - return {...prev, statusName: status ? status.name : ""} - }) - setOipc((prev) => { - return {...prev, outcomeName: outcome ? outcome.name : ""} - }) - setOipc((prev) => { - return {...prev, reasonName: reviewtype ? reviewtype.reason_name : ""} - }) - } const uniqueReviewTypes = (oipcReviewTypes) => { const uniqeValues = {}; return oipcReviewTypes.filter(reviewtype => !uniqeValues[reviewtype.type_name] && (uniqeValues[reviewtype.type_name] = true)); @@ -142,9 +124,10 @@ const OIPCItem = (props) => { useEffect(() => { setOipc(oipcObj); - generateNamesFromOIPCId(oipc); }, [oipcObj]) + console.log("OIPC", oipc) + return ( <>
From d98b520bb7547091771462ffe23c4ee72ecf6170 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Fri, 8 Dec 2023 13:46:55 -0800 Subject: [PATCH 112/238] Removal of uneeded code from OIPC Components in FE. Code Refactor --- .../src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index f175e9710..f9e890fbb 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -126,8 +126,6 @@ const OIPCItem = (props) => { setOipc(oipcObj); }, [oipcObj]) - console.log("OIPC", oipc) - return ( <>
From 4b7c8c903f4d09615af0e0323d156e98dd9d6b45 Mon Sep 17 00:00:00 2001 From: "sumathi.thirumani" Date: Fri, 8 Dec 2023 22:01:29 -0800 Subject: [PATCH 113/238] Changes to fix the duplicates in advanced search. --- .../request_api/models/FOIMinistryRequests.py | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index 89f7039e7..57eed14db 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -493,7 +493,7 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us ministry_restricted_requests.isrestricted.label('isministryrestricted'), SubjectCode.name.label('subjectcode'), FOIMinistryRequest.isoipcreview.label('isoipcreview'), - FOIRequestOIPC.oipcno.label('oipc_number') + literal(None).label('oipc_number'), ] basequery = _session.query( @@ -564,11 +564,9 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us SubjectCode, SubjectCode.subjectcodeid == FOIMinistryRequestSubjectCode.subjectcodeid, isouter=True - ).join( - FOIRequestOIPC, - and_(FOIRequestOIPC.foiministryrequest_id == FOIMinistryRequest.foiministryrequestid, FOIRequestOIPC.foiministryrequestversion_id == FOIMinistryRequest.version), - isouter=True ).filter(or_(FOIMinistryRequest.requeststatusid != 3, and_(FOIMinistryRequest.isoipcreview == True, FOIMinistryRequest.requeststatusid == 3))) + + if(additionalfilter == 'watchingRequests'): #watchby @@ -675,8 +673,7 @@ def findfield(cls, x, iaoassignee, ministryassignee): 'requestPageCount': FOIMinistryRequest.requestpagecount, 'closedate': FOIMinistryRequest.closedate, 'subjectcode': SubjectCode.name, - 'isoipcreview': FOIMinistryRequest.isoipcreview, - 'oipc_number': FOIRequestOIPC.oipcno + 'isoipcreview': FOIMinistryRequest.isoipcreview }.get(x, FOIMinistryRequest.axisrequestid) @classmethod @@ -1047,7 +1044,7 @@ def getbasequery(cls, iaoassignee, ministryassignee, userid=None, requestby='IAO ministry_restricted_requests.isrestricted.label('isministryrestricted'), SubjectCode.name.label('subjectcode'), FOIMinistryRequest.isoipcreview.label('isoipcreview'), - FOIRequestOIPC.oipcno.label('oipc_number') + literal(None).label('oipc_number') ] basequery = _session.query( @@ -1118,11 +1115,8 @@ def getbasequery(cls, iaoassignee, ministryassignee, userid=None, requestby='IAO SubjectCode, SubjectCode.subjectcodeid == FOIMinistryRequestSubjectCode.subjectcodeid, isouter=True - ).join( - FOIRequestOIPC, - and_(FOIRequestOIPC.foiministryrequest_id == FOIMinistryRequest.foiministryrequestid, FOIRequestOIPC.foiministryrequestversion_id == FOIMinistryRequest.version), - isouter=True ) + if(isiaorestrictedfilemanager == True or isministryrestrictedfilemanager == True): dbquery = basequery.filter(ministryfilter) @@ -1319,6 +1313,15 @@ def getfilterforsearch(cls, params, iaoassignee, ministryassignee): searchcondition1.append(FOIMinistryRequest.findfield('assignedministrypersonFirstName', iaoassignee, ministryassignee).ilike('%'+keyword+'%')) searchcondition2.append(FOIMinistryRequest.findfield('assignedministrypersonLastName', iaoassignee, ministryassignee).ilike('%'+keyword+'%')) return or_(and_(*searchcondition1), and_(*searchcondition2)) + elif(params['search'] == 'oipc_number'): + searchcondition1 = [] + searchcondition2 = [] + searchcondition3 = [] + for keyword in params['keywords']: + searchcondition1.append(FOIRequestOIPC.foiministryrequest_id == FOIMinistryRequest.foiministryrequestid) + searchcondition2.append(FOIRequestOIPC.foiministryrequestversion_id == FOIMinistryRequest.version) + searchcondition3.append(FOIRequestOIPC.oipcno.ilike('%'+keyword+'%')) + return and_(and_(*searchcondition1), and_(*searchcondition2), and_(*searchcondition3)) else: searchcondition = [] for keyword in params['keywords']: From e66e553998aad44ae81f4d95ff853d67adbb5ed0 Mon Sep 17 00:00:00 2001 From: "sumathi.thirumani" Date: Fri, 8 Dec 2023 23:52:54 -0800 Subject: [PATCH 114/238] Changes to return extact match --- .../request_api/models/FOIMinistryRequests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index 57eed14db..320affb59 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -1320,7 +1320,7 @@ def getfilterforsearch(cls, params, iaoassignee, ministryassignee): for keyword in params['keywords']: searchcondition1.append(FOIRequestOIPC.foiministryrequest_id == FOIMinistryRequest.foiministryrequestid) searchcondition2.append(FOIRequestOIPC.foiministryrequestversion_id == FOIMinistryRequest.version) - searchcondition3.append(FOIRequestOIPC.oipcno.ilike('%'+keyword+'%')) + searchcondition3.append(FOIRequestOIPC.oipcno==keyword) return and_(and_(*searchcondition1), and_(*searchcondition2), and_(*searchcondition3)) else: searchcondition = [] From 41eaaec0ad61209b7c82432ff7162b2bc306cee7 Mon Sep 17 00:00:00 2001 From: "sumathi.thirumani" Date: Sat, 9 Dec 2023 00:42:11 -0800 Subject: [PATCH 115/238] Changes to fix the duplicates in advanced search. --- .../request_api/models/FOIMinistryRequests.py | 9 ++++----- .../request_api/models/FOIRequestOIPC.py | 8 ++++++++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index 320affb59..dc25bc8ac 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -1316,12 +1316,11 @@ def getfilterforsearch(cls, params, iaoassignee, ministryassignee): elif(params['search'] == 'oipc_number'): searchcondition1 = [] searchcondition2 = [] - searchcondition3 = [] for keyword in params['keywords']: - searchcondition1.append(FOIRequestOIPC.foiministryrequest_id == FOIMinistryRequest.foiministryrequestid) - searchcondition2.append(FOIRequestOIPC.foiministryrequestversion_id == FOIMinistryRequest.version) - searchcondition3.append(FOIRequestOIPC.oipcno==keyword) - return and_(and_(*searchcondition1), and_(*searchcondition2), and_(*searchcondition3)) + oipccondition = FOIRequestOIPC.getrequestidsbyoipcno(keyword) + searchcondition1.append(oipccondition.c.foiministryrequest_id == FOIMinistryRequest.foiministryrequestid) + searchcondition2.append(oipccondition.c.foiministryrequestversion_id == FOIMinistryRequest.version) + return and_(and_(*searchcondition1), and_(*searchcondition2)) else: searchcondition = [] for keyword in params['keywords']: diff --git a/request-management-api/request_api/models/FOIRequestOIPC.py b/request-management-api/request_api/models/FOIRequestOIPC.py index a68407b9f..7add3afcd 100644 --- a/request-management-api/request_api/models/FOIRequestOIPC.py +++ b/request-management-api/request_api/models/FOIRequestOIPC.py @@ -47,6 +47,14 @@ def getoipc(cls,ministryrequestid,ministryrequestversion): divisioninfos = oipc_schema.dump(_oipclist) return divisioninfos + + @classmethod + def getrequestidsbyoipcno(cls, oipcno): + return db.session.query( + FOIRequestOIPC.foiministryrequest_id, + FOIRequestOIPC.foiministryrequestversion_id + ).filter(FOIRequestOIPC.oipcno.ilike('%'+oipcno+'%')).group_by(FOIRequestOIPC.foiministryrequest_id, FOIRequestOIPC.foiministryrequestversion_id).subquery() + class FOIRequestOIPCSchema(ma.Schema): class Meta: From df4a59706c1461e48904621b760e2f63ddaf09b1 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Mon, 11 Dec 2023 11:47:56 -0800 Subject: [PATCH 116/238] Bug fix for Jackie UX comments. adding a new oipc now does not trigger a reload of the page --- .../src/components/FOI/FOIRequest/OIPCDetails/Index.jsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx index 2d02e79e8..25248d58b 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/Index.jsx @@ -33,7 +33,10 @@ const OIPCDetails = (props) => {
-

Add Additional OIPC Complaint

From 04b95a4df3aa30bb224322f219857c9688a97d99 Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Mon, 11 Dec 2023 13:22:26 -0800 Subject: [PATCH 117/238] Change OIPC flag outline color and requestflag layout --- .../src/components/FOI/FOIRequest/FOIRequestHeader/index.js | 1 - .../src/components/FOI/customComponents/requestflag.scss | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js index 69c3ed18f..bfd71381a 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js @@ -288,7 +288,6 @@ const FOIRequestHeader = React.memo( }
-
Date: Mon, 11 Dec 2023 13:25:38 -0800 Subject: [PATCH 118/238] Remove closing div tag --- .../src/components/FOI/FOIRequest/FOIRequestHeader/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js index bfd71381a..85eb075a9 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js @@ -302,7 +302,6 @@ const FOIRequestHeader = React.memo( isActive={requestDetails.isphasedrelease} handleSelect={handleOipcReviewFlagChange} /> */} -
{showMinistryAssignedTo && ( From dc490a0889f4376a9e4ccfd0b0e8a77d240c0723 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Mon, 11 Dec 2023 14:00:38 -0800 Subject: [PATCH 119/238] Adjustments per Sumathi comments --- .../FOI/FOIRequest/OIPCDetails/oipcdetails.scss | 4 ++-- .../services/foirequest/requestserviceministrybuilder.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcdetails.scss b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcdetails.scss index d28779da2..9d467ac10 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcdetails.scss +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/oipcdetails.scss @@ -32,7 +32,7 @@ } .MuiDivider-root { - margin: 10px 0px 16px 0px !important; - height: 1.5px !important; + margin: 10px 0px 16px 0px; + height: 1.5px; } \ No newline at end of file diff --git a/request-management-api/request_api/services/foirequest/requestserviceministrybuilder.py b/request-management-api/request_api/services/foirequest/requestserviceministrybuilder.py index fca98fa3b..3c05ea9ba 100644 --- a/request-management-api/request_api/services/foirequest/requestserviceministrybuilder.py +++ b/request-management-api/request_api/services/foirequest/requestserviceministrybuilder.py @@ -88,7 +88,7 @@ def createfoiministryrequestfromobject(self, ministryschema, requestschema, user foiministryrequest.closedate = requestdict['closedate'] foiministryrequest.closereasonid = requestdict['closereasonid'] foiministryrequest.isoipcreview = ministryschema["isoipcreview"] - foiministryrequest.oipcreviews = self.createfoirequestoipcs(foiministryrequest.isoipcreview, ministryschema["foirequest_id"], ministryschema["version"], userid) + foiministryrequest.oipcreviews = self.createfoirequestoipcs(foiministryrequest.isoipcreview, ministryschema["foirequest_id"], ministryschema["version"], userid, usertype) return foiministryrequest def __createministrydivisions(self, requestschema, foiministryrequestid, foiministryrequestversion, userid): @@ -313,7 +313,7 @@ def createfoirequestdivision(self, requestschema, requestid, version, userid): def createfoiassigneefromobject(self, username, firstname, middlename, lastname): return FOIAssignee.saveassignee(username, firstname, middlename, lastname) - def createfoirequestoipcs(self, isoipcreview, requestid, version, userid): + def createfoirequestoipcs(self, isoipcreview, requestid, version, userid, usertype): current_oipcs = FOIRequestOIPC.getoipc(requestid, version) if (isoipcreview == True): updated_oipcs = [] @@ -336,8 +336,8 @@ def createfoirequestoipcs(self, isoipcreview, requestid, version, userid): oipcreview.isactive = True if oipc["isinquiry"] == True: oipcreview.inquiryattributes = oipc["inquiryattributes"] - oipcreview.createdby=userid - oipcreview.created_at= datetime2.now().isoformat() + oipcreview.createdby = oipc["createdby"] if usertype == "ministry" else userid + oipcreview.created_at= oipc["created_at"] if usertype == "ministry" else datetime2.now().isoformat() updated_oipcs.append(oipcreview) return updated_oipcs From e473e2ca0c8eda04a206df8417f74537172c063e Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Mon, 11 Dec 2023 16:45:46 -0800 Subject: [PATCH 120/238] Add responsiveness and update ministry view --- .../FOI/FOIRequest/FOIRequestHeader/index.js | 80 +++++++++++-------- .../MinistryReview/RequestHeader.js | 39 +++++---- .../FOI/customComponents/Watcher.scss | 5 +- 3 files changed, 70 insertions(+), 54 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js index 85eb075a9..c6e46aa8f 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js @@ -23,6 +23,7 @@ import _ from 'lodash'; import RequestRestriction from "../../customComponents/RequestRestriction"; import ConfirmModal from "../../customComponents/ConfirmModal"; import RequestFlag from '../../customComponents/RequestFlag'; +import { Grid } from '@material-ui/core'; const useStyles = makeStyles((theme) => ({ formControl: { @@ -265,43 +266,52 @@ const FOIRequestHeader = React.memo(
-
- {window.location.href.indexOf(FOI_COMPONENT_CONSTANTS.ADDREQUEST) === - -1 && ( - + + +
+ {window.location.href.indexOf(FOI_COMPONENT_CONSTANTS.ADDREQUEST) === + -1 && ( + + )} + {!isAddRequest && status.toLowerCase() !== StateEnum.unopened.name.toLowerCase() && (isIAORestrictedFileManager() || + (isLoaded && isRequestWatcherOrAssignee(requestWatchers,assigneeObj,userDetail?.preferred_username))) && + + + } +
+
+ +
+ - )} - {!isAddRequest && status.toLowerCase() !== StateEnum.unopened.name.toLowerCase() && (isIAORestrictedFileManager() || - (isLoaded && isRequestWatcherOrAssignee(requestWatchers,assigneeObj,userDetail?.preferred_username))) && - - - } + {/* */} +
+
+
-
- - {/* */}
{showMinistryAssignedTo && ( diff --git a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/RequestHeader.js b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/RequestHeader.js index 325d7007b..6bf01c04b 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/RequestHeader.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/RequestHeader.js @@ -1,5 +1,5 @@ import React, {useEffect, useState} from 'react'; -import { InputLabel } from '@material-ui/core'; +import { Grid, InputLabel } from '@material-ui/core'; import Link from '@material-ui/core/Link'; import TextField from '@material-ui/core/TextField'; import MinistryAssignToDropdown from '../MinistryAssignToDropdown'; @@ -108,6 +108,7 @@ const RequestHeader = React.memo(({ type="oipcreview" requestDetails={requestDetails} isActive={requestDetails.isoipcreview} + isDisabled={true} /> {/*
-
- {watcherBox} - { - (isLoaded && (isRequestWatcherOrMinistryAssignee(requestWatchers,ministryAssigneeValue,userDetail?.preferred_username) || - isMinistryRestrictedFileManager())) && - - } -
-
-
- {requestFlagsBox} -
+
+ + + {watcherBox} + { + (isLoaded && (isRequestWatcherOrMinistryAssignee(requestWatchers,ministryAssigneeValue,userDetail?.preferred_username) || + isMinistryRestrictedFileManager())) && + + } + + +
+ {requestFlagsBox} +
+
+
diff --git a/forms-flow-web/src/components/FOI/customComponents/Watcher.scss b/forms-flow-web/src/components/FOI/customComponents/Watcher.scss index 975751b07..9f674e35a 100644 --- a/forms-flow-web/src/components/FOI/customComponents/Watcher.scss +++ b/forms-flow-web/src/components/FOI/customComponents/Watcher.scss @@ -27,7 +27,7 @@ } .foi-eye-container { - width: auto; + width: 100px; height: 40px; background-color: #00336652; border-radius: 40px 0px 0px 40px; @@ -38,11 +38,12 @@ .foi-watcher-all { padding-top: 10px; display: flex; + width: 188px; } .foi-watcher-select { padding-top: 8px; - width: 80px; + width: 100px; height: 40px; background-color:#003366; color: white; From d6bed4cef0c81d24a55f23fe77b26af16635939c Mon Sep 17 00:00:00 2001 From: "sumathi.thirumani" Date: Mon, 11 Dec 2023 17:45:52 -0800 Subject: [PATCH 121/238] Remove reduntant property --- request-management-api/request_api/models/FOIRequestOIPC.py | 2 +- .../request_api/services/foirequest/requestservicebuilder.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/request-management-api/request_api/models/FOIRequestOIPC.py b/request-management-api/request_api/models/FOIRequestOIPC.py index 7add3afcd..2931a304a 100644 --- a/request-management-api/request_api/models/FOIRequestOIPC.py +++ b/request-management-api/request_api/models/FOIRequestOIPC.py @@ -59,5 +59,5 @@ def getrequestidsbyoipcno(cls, oipcno): class FOIRequestOIPCSchema(ma.Schema): class Meta: fields = ('oipcid', 'version', 'ministryrequestid', 'investigator','ministryversion','oipcno','reviewtypeid','reasonid','statusid','outcomeid','isinquiry','inquiryattributes','isjudicialreview', - 'issubsequentappeal','isactive','receiveddate','closeddate','created_at','createdby','updated_at','updatedby', + 'issubsequentappeal','receiveddate','closeddate','created_at','createdby','updated_at','updatedby', 'reviewtype.name', 'reason.name', 'status.name', 'outcome.name') \ No newline at end of file diff --git a/request-management-api/request_api/services/foirequest/requestservicebuilder.py b/request-management-api/request_api/services/foirequest/requestservicebuilder.py index b6315671b..dd1a0516b 100644 --- a/request-management-api/request_api/services/foirequest/requestservicebuilder.py +++ b/request-management-api/request_api/services/foirequest/requestservicebuilder.py @@ -151,7 +151,6 @@ def prepareoipc(self, requestschema, ministryrequestid, version, userid): oipcreview.issubsequentappeal = oipc["issubsequentappeal"] oipcreview.receiveddate = oipc["receiveddate"] if oipc["receiveddate"] not in (None, "") else None oipcreview.closeddate = oipc["closeddate"] if oipc["closeddate"] not in (None, "") else None - oipcreview.isactive = True if oipc["isinquiry"] == True: oipcreview.inquiryattributes = oipc["inquiryattributes"] oipcreview.createdby=userid From 4f434090b3f5f7aa3a65739e23b475198c9d6b46 Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Tue, 12 Dec 2023 11:22:39 -0800 Subject: [PATCH 122/238] Remove grid responsiveness --- .../src/components/FOI/FOIRequest/FOIRequestHeader/index.js | 4 ++-- .../components/FOI/FOIRequest/MinistryReview/RequestHeader.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js index c6e46aa8f..35c7813b8 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js @@ -268,7 +268,7 @@ const FOIRequestHeader = React.memo(
- +
{window.location.href.indexOf(FOI_COMPONENT_CONSTANTS.ADDREQUEST) === -1 && ( @@ -293,7 +293,7 @@ const FOIRequestHeader = React.memo( }
- +
- + {watcherBox} { (isLoaded && (isRequestWatcherOrMinistryAssignee(requestWatchers,ministryAssigneeValue,userDetail?.preferred_username) || @@ -159,7 +159,7 @@ const RequestHeader = React.memo(({ /> } - +
{requestFlagsBox}
From 36209e47b466eab1174d083f4dc52c09e5c28d32 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Tue, 12 Dec 2023 11:26:43 -0800 Subject: [PATCH 123/238] Adjusted per milos comments --- .../src/components/FOI/FOIRequest/FOIRequestHeader/index.js | 2 +- .../components/FOI/FOIRequest/MinistryReview/RequestHeader.js | 2 +- .../src/components/FOI/customComponents/RequestFlag.js | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js index ddca6cd7b..6331d9939 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js @@ -297,7 +297,7 @@ const FOIRequestHeader = React.memo( isActive={requestDetails.isoipcreview} handleSelect={handleOipcReviewFlagChange} showFlag={showOipcReviewFlag} - isMinistry={false} + isDisabled={isMinistry} /> {/* {/* { +const RequestFlag = ({ isActive, type, handleSelect, showFlag = true, isDisabled }) => { const [isSelected, setIsSelected] = useState(isActive || false); const [modalOpen, setModalOpen] = useState(false); const [modalHeading, setModalHeading] = useState(""); @@ -186,7 +186,7 @@ const RequestFlag = ({ isActive, type, handleSelect, showFlag = true, isMinistry onChange={handleValueChange} inputProps={{ "aria-labelledby": "restrict-dropdown-label" }} input={} - disabled={isMinistry} + disabled={isDisabled} > {options.map((option) => ( Date: Tue, 12 Dec 2023 16:54:03 -0800 Subject: [PATCH 124/238] Adjustments to UX for ticket 4776 + bug fix for save button active/inactive for ticket 4679 --- .../components/FOI/FOIRequest/FOIRequest.js | 10 ++-- .../OIPCDetails/OIPCDetailsMinistry.jsx | 53 +++++++++++++------ 2 files changed, 41 insertions(+), 22 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index 96c37d40a..fcdefaf3d 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -163,7 +163,7 @@ const FOIRequest = React.memo(({ userDetail }) => { const [attachments, setAttachments] = useState(requestAttachments); const [comment, setComment] = useState([]); const [requestState, setRequestState] = useState(StateEnum.unopened.name); - const [disableInput, setDisableInput] = useState(requestState?.toLowerCase() === StateEnum.closed.name.toLowerCase()); + const [disableInput, setDisableInput] = useState(requestState?.toLowerCase() === StateEnum.closed.name.toLowerCase() && !requestDetails?.isoipcreview); const [_tabStatus, settabStatus] = React.useState(requestState); let foitabheaderBG = getTabBG(_tabStatus, requestState); @@ -258,11 +258,11 @@ const FOIRequest = React.memo(({ userDetail }) => { const [isMCFPersonal, setIsMCFPersonal] = useState(bcgovcode.replaceAll('"', '') == "MCF" && requestDetails.requestType == FOI_COMPONENT_CONSTANTS.REQUEST_TYPE_PERSONAL); const {oipcData, addOIPC, removeOIPC, updateOIPC, isOIPCReview, setIsOIPCReview, removeAllOIPCs} = useOIPCHook(); const [oipcDataInitial, setOipcDataInitial] = useState(oipcData); - + //Update disableInput when requestState changes useEffect(() => { - setDisableInput(requestState?.toLowerCase() === StateEnum.closed.name.toLowerCase()) - }, [requestState]) + setDisableInput(requestState?.toLowerCase() === StateEnum.closed.name.toLowerCase() && !isOIPCReview); + }, [requestState, isOIPCReview]) useEffect(() => { if (!oipcDataInitial) { @@ -939,7 +939,7 @@ const FOIRequest = React.memo(({ userDetail }) => { requestDetails?.requestType === FOI_COMPONENT_CONSTANTS.REQUEST_TYPE_GENERAL) } - + return (!isLoading && requestDetails && Object.keys(requestDetails).length !== 0) || diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsMinistry.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsMinistry.jsx index 0c8ee81c0..ae2f181eb 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsMinistry.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCDetailsMinistry.jsx @@ -3,7 +3,7 @@ import './oipcdetails.scss'; const OIPCDetailsMinistry = (props) => { const {oipcData} = props; - + return ( @@ -57,87 +57,106 @@ const OIPCDetailsMinistry = (props) => { {oipc.status}
- + + {oipc.investigator &&
Investigator/Adjudicator
- {oipc.investigator ? oipc.investigator : "N/A"} + {oipc.investigator}
- + } + + {oipc.outcomeid &&
Outcome -
+
- {oipc.outcome ? oipc.outcome : "N/A"} + {oipc.outcome}
+ } + {oipc.closedate &&
Closed Date -
+
- {oipc.closedate ? oipc.closedate : "N/A"} + {oipc.closedate}
+ } + {oipc.isinquiry &&
In Inquiry? -
+
- {oipc.isinquiry ? "Yes" : "No"} + Yes
+ } + {oipc.inquiryattributes?.inquirydate &&
Inquiry Order Comply Date
- {oipc.inquiryattributes?.inquirydate ? oipc.inquiryattributes.inquirydate : "N/A"} + {oipc.inquiryattributes.inquirydate}
+ } + {oipc.inquiryattributes?.orderno &&
Inquiry Order No
- {oipc.inquiryattributes?.orderno ? oipc.inquiryattributes.orderno : "N/A"} + {oipc.inquiryattributes.orderno}
+ } + {oipc.inquiryattributes?.inquiryoutcome &&
Inquiry Outcome
- {oipc.inquiryattributes?.inquiryoutcome ? oipc.inquiryattributes.inquiryoutcome : "N/A"} + {oipc.inquiryattributes.inquiryoutcomename}
+ } + {oipc.isjudicialreview &&
In Judical Review? -
+
- {oipc.isjudicialreview ? "Yes" : "No"} + Yes
+ } + {oipc.issubsequentappeal &&
In Subsequent Appeal? -
+
- {oipc.issubsequentappeal ? "Yes" : "No"} + Yes
+ } +
{index !== (oipcData?.length - 1) && } From 896af905972549878ab0cf0e525534d7e6770593 Mon Sep 17 00:00:00 2001 From: "sumathi.thirumani" Date: Wed, 13 Dec 2023 00:00:11 -0800 Subject: [PATCH 125/238] Change comment type for displaying oipc under system generated. --- .../b4da31675bd0_oipc_commentype_change.py | 29 +++++++++++++++++++ .../request_api/services/events/oipc.py | 2 +- .../request_api/utils/enums.py | 1 - 3 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 request-management-api/migrations/versions/b4da31675bd0_oipc_commentype_change.py diff --git a/request-management-api/migrations/versions/b4da31675bd0_oipc_commentype_change.py b/request-management-api/migrations/versions/b4da31675bd0_oipc_commentype_change.py new file mode 100644 index 000000000..243d9d72b --- /dev/null +++ b/request-management-api/migrations/versions/b4da31675bd0_oipc_commentype_change.py @@ -0,0 +1,29 @@ +"""empty message + +Revision ID: b4da31675bd0 +Revises: 3e91d4f34699 +Create Date: 2023-12-12 23:18:19.440544 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = 'b4da31675bd0' +down_revision = '3e91d4f34699' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.execute('update public."FOIRequestComments" set commenttypeid = (select commenttypeid from "CommentTypes" where name = \'System generated\') where commenttypeid = (select commenttypeid from "CommentTypes" where name = \'OIPC Tracking\');commit;') + op.execute('delete from public."CommentTypes" where name in (\'OIPC Tracking\');commit;') + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.execute('delete from public."CommentTypes" where name in (\'OIPC Tracking\');commit;') + # ### end Alembic commands ### diff --git a/request-management-api/request_api/services/events/oipc.py b/request-management-api/request_api/services/events/oipc.py index 1742ca1b2..7899bb2d9 100644 --- a/request-management-api/request_api/services/events/oipc.py +++ b/request-management-api/request_api/services/events/oipc.py @@ -36,7 +36,7 @@ def createoipcevent(self, requestid, userid): def __createcomment(self, requestid, oipc, userid): comment = {"ministryrequestid": requestid, "comment": self.__preparemessage(oipc)} - commentservice().createministryrequestcomment(comment, userid, CommentType.OIPC.value) + commentservice().createministryrequestcomment(comment, userid, CommentType.SystemGenerated.value) def __createnotification(self, requestid, oipc, userid): return notificationservice().createnotification({"message" : self.__preparemessage(oipc)}, requestid, "ministryrequest", "OIPC", userid, False) diff --git a/request-management-api/request_api/utils/enums.py b/request-management-api/request_api/utils/enums.py index 2bad91da1..f21d807ab 100644 --- a/request-management-api/request_api/utils/enums.py +++ b/request-management-api/request_api/utils/enums.py @@ -132,7 +132,6 @@ class CommentType(Enum): UserComment = 1 SystemGenerated = 2 DivisionStages = 3 - OIPC = 4 class DocumentPathMapperCategory(Enum): Attachments = "Attachments" From 47360fbc1966a89f0b31025c720a2312b52d1bf4 Mon Sep 17 00:00:00 2001 From: Richard Qi Date: Wed, 13 Dec 2023 16:05:24 -0800 Subject: [PATCH 126/238] Initial check in for applicant profiles --- .../59a97f42b5f2_add_version_to_applicant.py | 30 ++ request-management-api/request_api/auth.py | 13 + .../models/FOIRequestApplicantMappings.py | 25 +- .../models/FOIRequestApplicants.py | 396 +++++++++++++++++- .../request_api/resources/__init__.py | 4 +- .../request_api/resources/foiapplicant.py | 93 ++++ .../request_api/services/applicantservice.py | 68 +++ 7 files changed, 621 insertions(+), 8 deletions(-) create mode 100644 request-management-api/migrations/versions/59a97f42b5f2_add_version_to_applicant.py create mode 100644 request-management-api/request_api/resources/foiapplicant.py create mode 100644 request-management-api/request_api/services/applicantservice.py diff --git a/request-management-api/migrations/versions/59a97f42b5f2_add_version_to_applicant.py b/request-management-api/migrations/versions/59a97f42b5f2_add_version_to_applicant.py new file mode 100644 index 000000000..d3abe9199 --- /dev/null +++ b/request-management-api/migrations/versions/59a97f42b5f2_add_version_to_applicant.py @@ -0,0 +1,30 @@ +"""add version to applicant + +Revision ID: 59a97f42b5f2 +Revises: 7fa7236d06fb +Create Date: 2023-12-11 18:12:59.955472 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '59a97f42b5f2' +down_revision = '7fa7236d06fb' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('FOIRequestApplicants', sa.Column('version', sa.Integer(), nullable=True)) + op.add_column('FOIRequestApplicantMappings', sa.Column('foirequestapplicant_version', sa.Integer(), nullable=True)) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('FOIRequestApplicants', 'version') + op.drop_column('FOIRequestApplicantMappings', 'foirequestapplicant_version') + # ### end Alembic commands ### diff --git a/request-management-api/request_api/auth.py b/request-management-api/request_api/auth.py index bacfb1607..386b68e03 100644 --- a/request-management-api/request_api/auth.py +++ b/request-management-api/request_api/auth.py @@ -144,6 +144,19 @@ def wrapper(*args, **kwargs): return wrapper return decorated + + @classmethod + def isiao(cls,func): + @wraps(func) + def decorated(type, id, field,*args, **kwargs): + usertype = AuthHelper.getusertype() + if(usertype == "iao"): + return func(type, id, field,*args, **kwargs) + else: + return "Unauthorized" , 401 + return decorated + + auth = ( Auth() ) diff --git a/request-management-api/request_api/models/FOIRequestApplicantMappings.py b/request-management-api/request_api/models/FOIRequestApplicantMappings.py index 877646a01..a2d284a36 100644 --- a/request-management-api/request_api/models/FOIRequestApplicantMappings.py +++ b/request-management-api/request_api/models/FOIRequestApplicantMappings.py @@ -5,6 +5,7 @@ from sqlalchemy.orm import relationship,backref from .default_method_result import DefaultMethodResult from .FOIRequests import FOIRequest +from sqlalchemy import and_, or_ class FOIRequestApplicantMapping(db.Model): # Name of the table in our database @@ -28,17 +29,33 @@ class FOIRequestApplicantMapping(db.Model): requestortype = relationship("RequestorType",backref=backref("RequestorTypes"),uselist=False) foirequestapplicantid = db.Column(db.Integer,ForeignKey('FOIRequestApplicants.foirequestapplicantid')) - foirequestapplicant = relationship("FOIRequestApplicant",backref=backref("FOIRequestApplicants"),uselist=False) + foirequestapplicant_version = db.Column(db.Integer, ForeignKey('FOIRequestApplicants.version')) + foirequestapplicant = relationship('FOIRequestApplicant', primaryjoin="and_(FOIRequestApplicant.foirequestapplicantid==FOIRequestApplicantMapping.foirequestapplicantid, " + "FOIRequestApplicant.version==FOIRequestApplicantMapping.foirequestapplicant_version)") - foirequest_id =db.Column(db.Integer, db.ForeignKey('FOIRequests.foirequestid')) - foirequestversion_id = db.Column(db.Integer, db.ForeignKey('FOIRequests.version')) + foirequest_id =db.Column(db.Integer, ForeignKey('FOIRequests.foirequestid')) + foirequestversion_id = db.Column(db.Integer, ForeignKey('FOIRequests.version')) foirequestkey = relationship("FOIRequest",foreign_keys="[FOIRequestApplicantMapping.foirequest_id]") foirequestversion = relationship("FOIRequest",foreign_keys="[FOIRequestApplicantMapping.foirequestversion_id]") @classmethod def getrequestapplicants(cls,foirequest_id,foirequestversion): + from .FOIRequestApplicants import FOIRequestApplicant requestapplicant_schema = FOIRequestApplicantMappingSchema(many=True) - _applicantinfos = db.session.query(FOIRequestApplicantMapping).filter(FOIRequestApplicantMapping.foirequest_id == foirequest_id , FOIRequestApplicantMapping.foirequestversion_id == foirequestversion).order_by(FOIRequestApplicantMapping.foirequestapplicantmappingid.asc()).all() + _applicantinfos = db.session.query(FOIRequestApplicantMapping + ).join( + FOIRequestApplicant, + and_( + FOIRequestApplicant.foirequestapplicantid == FOIRequestApplicantMapping.foirequestapplicantid, + or_( + FOIRequestApplicant.version == FOIRequestApplicantMapping.foirequestapplicant_version, + FOIRequestApplicantMapping.foirequestapplicant_version is None + ) + ) + ).filter( + FOIRequestApplicantMapping.foirequest_id == foirequest_id, + FOIRequestApplicantMapping.foirequestversion_id == foirequestversion + ).order_by(FOIRequestApplicantMapping.foirequestapplicantmappingid.asc()).all() applicantinfos = requestapplicant_schema.dump(_applicantinfos) return applicantinfos diff --git a/request-management-api/request_api/models/FOIRequestApplicants.py b/request-management-api/request_api/models/FOIRequestApplicants.py index 7f4f8f1ad..edf66e47d 100644 --- a/request-management-api/request_api/models/FOIRequestApplicants.py +++ b/request-management-api/request_api/models/FOIRequestApplicants.py @@ -2,9 +2,14 @@ from sqlalchemy.sql.schema import ForeignKey, ForeignKeyConstraint from .db import db, ma from datetime import datetime -from sqlalchemy.orm import relationship,backref +from sqlalchemy.orm import relationship, backref, aliased from .default_method_result import DefaultMethodResult +from .FOIRequestApplicantMappings import FOIRequestApplicantMapping +from .ApplicantCategories import ApplicantCategory from .FOIRequests import FOIRequest +from .FOIRequestContactInformation import FOIRequestContactInformation +from .FOIRequestPersonalAttributes import FOIRequestPersonalAttribute +from sqlalchemy import and_, or_, asc, func class FOIRequestApplicant(db.Model): # Name of the table in our database @@ -25,6 +30,7 @@ class FOIRequestApplicant(db.Model): updated_at = db.Column(db.DateTime, nullable=True) createdby = db.Column(db.String(120), unique=False, nullable=True) updatedby = db.Column(db.String(120), unique=False, nullable=True) + version = db.Column(db.Integer, unique=False, nullable=True) @classmethod def saveapplicant(cls,firstname, lastname, middlename, businessname, alsoknownas, dob, userid): @@ -60,8 +66,392 @@ def saveapplicant(cls,firstname, lastname, middlename, businessname, alsoknownas db.session.add(applicant) db.session.commit() return DefaultMethodResult(True,'Applicant added',applicant.foirequestapplicantid) - + + # Search applicant by email + @classmethod + def getapplicantbyemail(cls, email): + from .FOIMinistryRequests import FOIMinistryRequest + + #for queue/dashboard + _session = db.session + + #aliase for getting contact info + contactemail = aliased(FOIRequestContactInformation) + contactaddress = aliased(FOIRequestContactInformation) + contacthomephone = aliased(FOIRequestContactInformation) + contactworkphone = aliased(FOIRequestContactInformation) + contactworkphone2 = aliased(FOIRequestContactInformation) + contactmobilephone = aliased(FOIRequestContactInformation) + contactother = aliased(FOIRequestContactInformation) + + #aliase for getting personal attributes + personalemployeenumber = aliased(FOIRequestPersonalAttribute) + personalcorrectionnumber = aliased(FOIRequestPersonalAttribute) + personalhealthnumber = aliased(FOIRequestPersonalAttribute) + + #max foirequest version + subquery_foirequest_maxversion = _session.query(FOIRequest.foirequestid, func.max(FOIRequest.version).label('max_version')).group_by(FOIRequest.foirequestid).subquery() + joincondition = [ + subquery_foirequest_maxversion.c.foirequestid == FOIRequest.foirequestid, + subquery_foirequest_maxversion.c.max_version == FOIRequest.version, + ] + + #generate query + selectedcolumns = [ + FOIRequestApplicant.foirequestapplicantid.label('foirequestapplicantid'), + FOIRequestApplicant.firstname.label('firstname'), + FOIRequestApplicant.middlename.label('middlename'), + FOIRequestApplicant.lastname.label('lastname'), + FOIRequestApplicant.alsoknownas.label('alsoknownas'), + FOIRequestApplicant.dob.label('dob'), + FOIRequestApplicant.businessname.label('businessname'), + FOIRequestApplicant.version.label('applicantversion'), + FOIRequest.foirequestid.label('foirequestid'), + FOIRequest.version.label('foirequestversion'), + FOIRequest.requesttype.label('requesttype'), + ApplicantCategory.name.label('applicantcategory'), + contactemail.contactinformation.label('email'), + contactaddress.contactinformation.label('address'), + contacthomephone.contactinformation.label('homephone'), + contactworkphone.contactinformation.label('workphone'), + contactworkphone2.contactinformation.label('workphone2'), + contactmobilephone.contactinformation.label('mobilephone'), + contactother.contactinformation.label('othercontactinfo'), + personalemployeenumber.attributevalue.label('employeenumber'), + personalcorrectionnumber.attributevalue.label('correctionnumber'), + personalhealthnumber.attributevalue.label('phn') + ] + + applicantprofile_schema = ApplicantProfileSchema(many=True) + query = _session.query( + *selectedcolumns + ).join( + FOIRequestApplicantMapping, + and_( + FOIRequestApplicantMapping.foirequest_id == FOIRequest.foirequestid, + FOIRequestApplicantMapping.foirequestversion_id == FOIRequest.version, + FOIRequestApplicantMapping.requestortypeid == 1), + ).join( + FOIRequestApplicant, + # FOIRequestApplicant.foirequestapplicantid == FOIRequestApplicantMapping.foirequestapplicantid + and_( + FOIRequestApplicant.foirequestapplicantid == FOIRequestApplicantMapping.foirequestapplicantid, + or_( + FOIRequestApplicant.version == None, + FOIRequestApplicantMapping.foirequestapplicant_version == None, + FOIRequestApplicant.version == FOIRequestApplicantMapping.foirequestapplicant_version + ) + ) + ).join( + ApplicantCategory, + ApplicantCategory.applicantcategoryid == FOIRequest.applicantcategoryid + ).join( + subquery_foirequest_maxversion, + and_(*joincondition) + ).join( + FOIMinistryRequest, + and_( + FOIMinistryRequest.foirequest_id == FOIRequest.foirequestid, + FOIMinistryRequest.isactive == True) + ).join( + contactemail, + and_( + contactemail.foirequest_id == FOIRequest.foirequestid, + contactemail.foirequestversion_id == FOIRequest.version, + contactemail.contacttypeid == 1), + ).join( + contactaddress, + and_( + contactaddress.foirequest_id == FOIRequest.foirequestid, + contactaddress.foirequestversion_id == FOIRequest.version, + contactaddress.contacttypeid == 2, + contactaddress.contactinformation is not None), + isouter=True + ).join( + contacthomephone, + and_( + contacthomephone.foirequest_id == FOIRequest.foirequestid, + contacthomephone.foirequestversion_id == FOIRequest.version, + contacthomephone.contacttypeid == 3, + contacthomephone.contactinformation is not None), + isouter=True + ).join( + contactworkphone, + and_( + contactworkphone.foirequest_id == FOIRequest.foirequestid, + contactworkphone.foirequestversion_id == FOIRequest.version, + contactworkphone.contacttypeid == 4, + contactworkphone.contactinformation is not None), + isouter=True + ).join( + contactworkphone2, + and_( + contactworkphone2.foirequest_id == FOIRequest.foirequestid, + contactworkphone2.foirequestversion_id == FOIRequest.version, + contactworkphone2.contacttypeid == 5, + contactworkphone2.contactinformation is not None), + isouter=True + ).join( + contactmobilephone, + and_( + contactmobilephone.foirequest_id == FOIRequest.foirequestid, + contactmobilephone.foirequestversion_id == FOIRequest.version, + contactmobilephone.contacttypeid == 6, + contactmobilephone.contactinformation is not None), + isouter=True + ).join( + contactother, + and_( + contactother.foirequest_id == FOIRequest.foirequestid, + contactother.foirequestversion_id == FOIRequest.version, + contactother.contacttypeid == 7, + contactother.contactinformation is not None), + isouter=True + ).join( + personalemployeenumber, + and_( + personalemployeenumber.foirequest_id == FOIRequest.foirequestid, + personalemployeenumber.foirequestversion_id == FOIRequest.version, + personalemployeenumber.personalattributeid == 1, + personalemployeenumber.attributevalue is not None), + isouter=True + ).join( + personalcorrectionnumber, + and_( + personalcorrectionnumber.foirequest_id == FOIRequest.foirequestid, + personalcorrectionnumber.foirequestversion_id == FOIRequest.version, + personalcorrectionnumber.personalattributeid == 2, + personalcorrectionnumber.attributevalue is not None), + isouter=True + ).join( + personalhealthnumber, + and_( + personalhealthnumber.foirequest_id == FOIRequest.foirequestid, + personalhealthnumber.foirequestversion_id == FOIRequest.version, + personalhealthnumber.personalattributeid == 3, + personalhealthnumber.attributevalue is not None), + isouter=True + ).filter( + FOIMinistryRequest.requeststatusid != 3, + FOIRequest.isactive == True, + contactemail.contactinformation == email + ).order_by(FOIRequest.foirequestid.asc()) + + print("query: ", query) + # print("result: ", query.all()) + return applicantprofile_schema.dump(query.all()) + + + # Search applicant by keywords + @classmethod + def searchapplicant(cls, keywords): + from .FOIMinistryRequests import FOIMinistryRequest + + #for queue/dashboard + _session = db.session + + #aliase for getting contact info + contactemail = aliased(FOIRequestContactInformation) + contactaddress = aliased(FOIRequestContactInformation) + contacthomephone = aliased(FOIRequestContactInformation) + contactworkphone = aliased(FOIRequestContactInformation) + contactworkphone2 = aliased(FOIRequestContactInformation) + contactmobilephone = aliased(FOIRequestContactInformation) + contactother = aliased(FOIRequestContactInformation) + + #aliase for getting personal attributes + personalemployeenumber = aliased(FOIRequestPersonalAttribute) + personalcorrectionnumber = aliased(FOIRequestPersonalAttribute) + personalhealthnumber = aliased(FOIRequestPersonalAttribute) + + #max foirequest version + subquery_foirequest_maxversion = _session.query(FOIRequest.foirequestid, func.max(FOIRequest.version).label('max_version')).group_by(FOIRequest.foirequestid).subquery() + joincondition = [ + subquery_foirequest_maxversion.c.foirequestid == FOIRequest.foirequestid, + subquery_foirequest_maxversion.c.max_version == FOIRequest.version, + ] + + #generate query + selectedcolumns = [ + FOIRequestApplicant.foirequestapplicantid.label('foirequestapplicantid'), + FOIRequestApplicant.firstname.label('firstname'), + FOIRequestApplicant.middlename.label('middlename'), + FOIRequestApplicant.lastname.label('lastname'), + FOIRequestApplicant.alsoknownas.label('alsoknownas'), + FOIRequestApplicant.dob.label('dob'), + FOIRequestApplicant.businessname.label('businessname'), + FOIRequestApplicant.version.label('applicantversion'), + FOIRequest.foirequestid.label('foirequestid'), + FOIRequest.version.label('foirequestversion'), + FOIRequest.requesttype.label('requesttype'), + ApplicantCategory.name.label('applicantcategory'), + contactemail.contactinformation.label('email'), + contactaddress.contactinformation.label('address'), + contacthomephone.contactinformation.label('homephone'), + contactworkphone.contactinformation.label('workphone'), + contactworkphone2.contactinformation.label('workphone2'), + contactmobilephone.contactinformation.label('mobilephone'), + contactother.contactinformation.label('othercontactinfo'), + personalemployeenumber.attributevalue.label('employeenumber'), + personalcorrectionnumber.attributevalue.label('correctionnumber'), + personalhealthnumber.attributevalue.label('phn') + ] + + applicantprofile_schema = ApplicantProfileSchema(many=True) + query = _session.query( + *selectedcolumns + ).join( + FOIRequestApplicantMapping, + and_( + FOIRequestApplicantMapping.foirequest_id == FOIRequest.foirequestid, + FOIRequestApplicantMapping.foirequestversion_id == FOIRequest.version, + FOIRequestApplicantMapping.requestortypeid == 1), + ).join( + FOIRequestApplicant, + # FOIRequestApplicant.foirequestapplicantid == FOIRequestApplicantMapping.foirequestapplicantid + and_( + FOIRequestApplicant.foirequestapplicantid == FOIRequestApplicantMapping.foirequestapplicantid, + or_( + FOIRequestApplicant.version == None, + FOIRequestApplicantMapping.foirequestapplicant_version == None, + FOIRequestApplicant.version == FOIRequestApplicantMapping.foirequestapplicant_version + ) + ) + ).join( + ApplicantCategory, + ApplicantCategory.applicantcategoryid == FOIRequest.applicantcategoryid + ).join( + subquery_foirequest_maxversion, + and_(*joincondition) + ).join( + FOIMinistryRequest, + and_( + FOIMinistryRequest.foirequest_id == FOIRequest.foirequestid, + FOIMinistryRequest.isactive == True) + ).join( + contactemail, + and_( + contactemail.foirequest_id == FOIRequest.foirequestid, + contactemail.foirequestversion_id == FOIRequest.version, + contactemail.contacttypeid == 1), + isouter=True + ).join( + contactaddress, + and_( + contactaddress.foirequest_id == FOIRequest.foirequestid, + contactaddress.foirequestversion_id == FOIRequest.version, + contactaddress.contacttypeid == 2, + contactaddress.contactinformation is not None), + isouter=True + ).join( + contacthomephone, + and_( + contacthomephone.foirequest_id == FOIRequest.foirequestid, + contacthomephone.foirequestversion_id == FOIRequest.version, + contacthomephone.contacttypeid == 3, + contacthomephone.contactinformation is not None), + isouter=True + ).join( + contactworkphone, + and_( + contactworkphone.foirequest_id == FOIRequest.foirequestid, + contactworkphone.foirequestversion_id == FOIRequest.version, + contactworkphone.contacttypeid == 4, + contactworkphone.contactinformation is not None), + isouter=True + ).join( + contactworkphone2, + and_( + contactworkphone2.foirequest_id == FOIRequest.foirequestid, + contactworkphone2.foirequestversion_id == FOIRequest.version, + contactworkphone2.contacttypeid == 5, + contactworkphone2.contactinformation is not None), + isouter=True + ).join( + contactmobilephone, + and_( + contactmobilephone.foirequest_id == FOIRequest.foirequestid, + contactmobilephone.foirequestversion_id == FOIRequest.version, + contactmobilephone.contacttypeid == 6, + contactmobilephone.contactinformation is not None), + isouter=True + ).join( + contactother, + and_( + contactother.foirequest_id == FOIRequest.foirequestid, + contactother.foirequestversion_id == FOIRequest.version, + contactother.contacttypeid == 7, + contactother.contactinformation is not None), + isouter=True + ).join( + personalemployeenumber, + and_( + personalemployeenumber.foirequest_id == FOIRequest.foirequestid, + personalemployeenumber.foirequestversion_id == FOIRequest.version, + personalemployeenumber.personalattributeid == 1, + personalemployeenumber.attributevalue is not None), + isouter=True + ).join( + personalcorrectionnumber, + and_( + personalcorrectionnumber.foirequest_id == FOIRequest.foirequestid, + personalcorrectionnumber.foirequestversion_id == FOIRequest.version, + personalcorrectionnumber.personalattributeid == 2, + personalcorrectionnumber.attributevalue is not None), + isouter=True + ).join( + personalhealthnumber, + and_( + personalhealthnumber.foirequest_id == FOIRequest.foirequestid, + personalhealthnumber.foirequestversion_id == FOIRequest.version, + personalhealthnumber.personalattributeid == 3, + personalhealthnumber.attributevalue is not None), + isouter=True + ).filter( + FOIMinistryRequest.requeststatusid != 3, + FOIRequest.isactive == True, + or_(*FOIRequestApplicant.getsearchfilters(keywords, contactemail, contacthomephone, contactworkphone, contactworkphone2, contactmobilephone)) + ).order_by(FOIRequest.foirequestid.asc()) + + # print("query: ", query) + # print("result: ", query.all()) + return applicantprofile_schema.dump(query.all()) + + + @classmethod + def getsearchfilters(cls, keywords, contactemail, contacthomephone, contactworkphone, contactworkphone2, contactmobilephone): + searchfilters = [] + if(len(keywords) > 0): + if(keywords['firstname'] is not None): + searchfilters.append(FOIRequestApplicant.firstname.ilike('%'+keywords['firstname']+'%')) + + if(keywords['lastname'] is not None): + searchfilters.append(FOIRequestApplicant.lastname.ilike('%'+keywords['lastname']+'%')) + + if(keywords['email'] is not None): + searchfilters.append(contactemail.contactinformation.ilike('%'+keywords['email']+'%')) + + if(keywords['homephone'] is not None): + searchfilters.append(contacthomephone.contactinformation.ilike('%'+keywords['homephone']+'%')) + + if(keywords['workphone'] is not None): + searchfilters.append(contactworkphone.contactinformation.ilike('%'+keywords['workphone']+'%')) + + if(keywords['workphone2'] is not None): + searchfilters.append(contactworkphone2.contactinformation.ilike('%'+keywords['workphone2']+'%')) + + if(keywords['mobilephone'] is not None): + searchfilters.append(contactmobilephone.contactinformation.ilike('%'+keywords['mobilephone']+'%')) + + return searchfilters + class FOIRequestApplicantSchema(ma.Schema): class Meta: fields = ('foirequestapplicantid','firstname','middlename','lastname','alsoknownas','dob','businessname') - \ No newline at end of file + +class ApplicantProfileSchema(ma.Schema): + class Meta: + fields = ('foirequestapplicantid','firstname','middlename','lastname','alsoknownas','dob', + 'businessname','applicantversion','foirequestid','foirequestversion','requesttype', + 'applicantcategory','email','address','homephone','workphone','workphone2','mobilephone', + 'othercontactinfo','employeenumber','correctionnumber','phn') diff --git a/request-management-api/request_api/resources/__init__.py b/request-management-api/request_api/resources/__init__.py index 403e0cb47..9eeaf75fa 100644 --- a/request-management-api/request_api/resources/__init__.py +++ b/request-management-api/request_api/resources/__init__.py @@ -49,6 +49,7 @@ from .foiworkflow import API as FOIWORKFLOW_API from .dashboardeventpagination import API as FOIEVENT_API from .foiuser import API as FOIUSER_API +from .foiapplicant import API as APPLICANT_API __all__ = ('API_BLUEPRINT') @@ -91,4 +92,5 @@ API.add_namespace(APPLICANTCORRESPONDENCE_API, '/api') API.add_namespace(FOIWORKFLOW_API, '/api') API.add_namespace(FOIEVENT_API, '/api') -API.add_namespace(FOIUSER_API, '/api') \ No newline at end of file +API.add_namespace(FOIUSER_API, '/api') +API.add_namespace(APPLICANT_API, '/api') \ No newline at end of file diff --git a/request-management-api/request_api/resources/foiapplicant.py b/request-management-api/request_api/resources/foiapplicant.py new file mode 100644 index 000000000..20142b4fd --- /dev/null +++ b/request-management-api/request_api/resources/foiapplicant.py @@ -0,0 +1,93 @@ +# Copyright © 2021 Province of British Columbia +# +# Licensed under the Apache License, Version 2.0 (the 'License'); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an 'AS IS' BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""API endpoints for managing a FOI Requests resource.""" + + +from flask import g, request +import flask +from flask_restx import Namespace, Resource, cors +from flask_expects_json import expects_json +from request_api.auth import auth +from request_api.tracer import Tracer +from request_api.utils.util import cors_preflight, allowedorigins +from request_api.exceptions import BusinessException, Error +from request_api.services.applicantservice import applicantservice +import json +from flask_cors import cross_origin +import request_api +from request_api.utils.cache import cache_filter, response_filter + +API = Namespace('FOIAssignee', description='Endpoints for FOI assignee management') +TRACER = Tracer.get_instance() + +"""Custom exception messages +""" +EXCEPTION_MESSAGE_BAD_REQUEST='Bad Request' +EXCEPTION_MESSAGE_NOT_FOUND='Not Found' + + +@cors_preflight('GET,OPTIONS') +@API.route('/foiapplicants/') +class FOIApplicants(Resource): + """Resource for retriving all FOI assignees.""" + + @staticmethod + @TRACER.trace() + @cross_origin(origins=allowedorigins()) + # @auth.require + # @auth.isiao + @cors_preflight('GET,OPTIONS') + def get(email=None): + print(email) + + if email is None or email == "": + return {'status': False, 'message':EXCEPTION_MESSAGE_BAD_REQUEST}, 400 + try: + result = applicantservice().getapplicantbyemail(email) + print("result-endpoint: ", result) + if result is not None: + return json.dumps(result), 200 + else: + return {'status': False, 'message':EXCEPTION_MESSAGE_NOT_FOUND}, 404 + except BusinessException as exception: + return {'status': exception.status_code, 'message':exception.message}, 500 + + +@cors_preflight('GET,OPTIONS') +@API.route('/foiapplicants/search') +class EventPagination(Resource): + """ Retrives the foi request based on the queue type. + """ + @staticmethod + @TRACER.trace() + @cross_origin(origins=allowedorigins()) + # @auth.require + # @auth.isiao + @cors_preflight('GET,OPTIONS') + def get(): + try: + _keywords = flask.request.args.get('keywords', None, type=str) + print(_keywords) + + result = [] + statuscode = 200 + if _keywords is None or _keywords == "": + result = applicantservice().searchapplicant(_keywords) + else: + statuscode = 401 + + return result, statuscode + except BusinessException as exception: + return {'status': exception.status_code, 'message':exception.message}, 500 + diff --git a/request-management-api/request_api/services/applicantservice.py b/request-management-api/request_api/services/applicantservice.py new file mode 100644 index 000000000..59c890f28 --- /dev/null +++ b/request-management-api/request_api/services/applicantservice.py @@ -0,0 +1,68 @@ + +from os import stat +from re import VERBOSE +from request_api.models.FOIRequestApplicants import FOIRequestApplicant +from request_api.auth import AuthHelper +from dateutil import tz, parser +from flask import jsonify +from datetime import datetime as datetime2 +from request_api.utils.commons.datetimehandler import datetimehandler +import re + +class applicantservice: + """ FOI Event Dashboard + """ + + def getapplicantbyemail(self, email): + applicantqueue = [] + applicants = FOIRequestApplicant.getapplicantbyemail(email) + print('applicants: ', applicants) + if applicants is not None: + for applicant in applicants: + applicantqueue.append(self.__prepareapplicant(applicant)) + + return applicantqueue + + def searchapplicant(self, keywords): + applicantqueue = [] + applicants = FOIRequestApplicant.searchapplicant(keywords) + if applicants is not None: + for applicant in applicants: + applicantqueue.append(self.__prepareapplicant(applicant)) + + return applicantqueue + + def __validateandtransform(self, filterfields): + return self.__transformfilteringfields(filterfields) + + def __transformfilteringfields(self, filterfields): + return list(map(lambda x: x.replace('createdat', 'createdatformatted'), filterfields)) + + def __prepareapplicant(self, applicant): + return { + 'foirequestapplicantid': applicant["foirequestapplicantid"], + 'firstname': applicant["firstname"], + 'middlename': applicant["middlename"], + 'lastname': applicant["lastname"], + 'alsoknownas': applicant["alsoknownas"], + 'dob' : applicant["dob"], + #'createdat' : self.__formatedate(applicant["createdat)"], + 'businessname': applicant["businessname"], + # 'applicant': applicant["applicant"], + 'applicantversion': applicant["applicantversion"], + 'foirequestid': applicant["foirequestid"], + 'foirequestversion': applicant["foirequestversion"], + 'requesttype': applicant["requesttype"], + 'applicantcategory': applicant["applicantcategory"], + 'email':applicant["email"], + 'address': applicant["address"], + 'homephone': applicant["homephone"], + 'workphone': applicant["workphone"], + 'workphone2': applicant["workphone2"], + 'mobilephone': applicant["mobilephone"], + 'othercontactinfo':applicant["othercontactinfo"], + 'employeenumber': applicant["employeenumber"], + 'correctionnumber': applicant["correctionnumber"], + 'phn':applicant["phn"] + } + \ No newline at end of file From 6f7b6a3104f7313d55d4672889aeb6fc471fa6c8 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Wed, 13 Dec 2023 16:14:50 -0800 Subject: [PATCH 127/238] Delete all oipc end point created + API call to new endpoint added in FE --- .../services/FOI/foiRequestServices.js | 24 +++++++++ .../components/FOI/FOIRequest/FOIRequest.js | 53 ++++++++++++++++--- .../request_api/resources/foirequest.py | 31 ++++++++++- 3 files changed, 100 insertions(+), 8 deletions(-) diff --git a/forms-flow-web/src/apiManager/services/FOI/foiRequestServices.js b/forms-flow-web/src/apiManager/services/FOI/foiRequestServices.js index 0d0c017ab..9ca09eb2c 100644 --- a/forms-flow-web/src/apiManager/services/FOI/foiRequestServices.js +++ b/forms-flow-web/src/apiManager/services/FOI/foiRequestServices.js @@ -525,3 +525,27 @@ export const fetchRestrictedRequestCommentTagList = (requestid, ministryId, ...r } }; +export const deleteOIPCDetails = (requestId, ministryId, ...rest) => { + const done = fnDone(rest); + let apiUrl= replaceUrl(replaceUrl( + API.FOI_REQUEST_API, + "", + ministryId),"",requestId + ); + const data = {isoipcreview: false, oipcdetails: []} + return (dispatch) => { + httpPOSTRequest(`${apiUrl}/deleteoipc`, data) + .then((res) => { + if (res.data) { + done(null, res.data); + } else { + dispatch(serviceActionError(res)); + throw new Error(`Error while saving the OIPC Details for the (request# ${requestId}, ministry# ${ministryId})`); + } + }) + .catch((error) => { + done(error); + catchError(error, dispatch); + }); + }; +} \ No newline at end of file diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index fcdefaf3d..90fe23919 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -34,6 +34,7 @@ import { fetchFOIRequestDescriptionList, fetchRequestDataFromAxis, fetchRestrictedRequestCommentTagList, + deleteOIPCDetails } from "../../../apiManager/services/FOI/foiRequestServices"; import { fetchFOIRequestAttachmentsList } from "../../../apiManager/services/FOI/foiAttachmentServices"; import { fetchCFRForm } from "../../../apiManager/services/FOI/foiCFRFormServices"; @@ -87,6 +88,7 @@ import DivisionalTracking from "./DivisionalTracking"; import RedactionSummary from "./RedactionSummary"; import AxisDetails from "./AxisDetails/AxisDetails"; import AxisMessageBanner from "./AxisDetails/AxisMessageBanner"; +import { toast } from "react-toastify"; import HomeIcon from "@mui/icons-material/Home"; import { RecordsLog } from "../customComponents/Records"; import { UnsavedModal } from "../customComponents"; @@ -663,16 +665,51 @@ const FOIRequest = React.memo(({ userDetail }) => { setAssignedToValue(value); }; + const saveOIPCNoReview = () => { + removeAllOIPCs(); + setIsOIPCReview(false); + dispatch( + deleteOIPCDetails( + requestId, + ministryId, + (err, _res) => { + if(!err) { + toast.success("OIPC details have been saved successfully.", { + position: "top-right", + autoClose: 3000, + hideProgressBar: true, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + }); + } else { + toast.error( + "Temporarily unable to save the OIPC details. Please try again in a few minutes.", + { + position: "top-right", + autoClose: 3000, + hideProgressBar: true, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + } + ); + } + }) + ) + } + const oipcSectionRef = React.useRef(null); const handleOipcReviewFlagChange = (isSelected) => { if (!isSelected) { - removeAllOIPCs(); - } - setIsOIPCReview(isSelected); - requestDetails.isoipcreview = isSelected; - oipcSectionRef.current.scrollIntoView(); - //timeout to allow react state to update after setState call - if (isSelected) { + saveOIPCNoReview(); + } else { + setIsOIPCReview(isSelected); + requestDetails.isoipcreview = isSelected; + oipcSectionRef.current.scrollIntoView(); + //timeout to allow react state to update after setState call setTimeout(() => { oipcSectionRef.current.scrollIntoView(); }, (10)); @@ -939,6 +976,8 @@ const FOIRequest = React.memo(({ userDetail }) => { requestDetails?.requestType === FOI_COMPONENT_CONSTANTS.REQUEST_TYPE_GENERAL) } + console.log(requestDetails) + return (!isLoading && requestDetails && diff --git a/request-management-api/request_api/resources/foirequest.py b/request-management-api/request_api/resources/foirequest.py index 290cd2ccc..991853602 100644 --- a/request-management-api/request_api/resources/foirequest.py +++ b/request-management-api/request_api/resources/foirequest.py @@ -136,7 +136,7 @@ class FOIRequestsById(Resource): def post(foirequestid,foiministryrequestid): """ POST Method for capturing FOI requests before processing""" try: - request_json = request.get_json() + request_json = request.get_json() foirequestschema = FOIRequestWrapperSchema().load(request_json) result = requestservice().saverequestversion(foirequestschema, foirequestid, foiministryrequestid,AuthHelper.getuserid()) if result.success == True: @@ -289,5 +289,34 @@ def get(ministryrequestid,usertype=None): return FOIRequest.get(requestservice().getrequestid(ministryrequestid), ministryrequestid, usertype) except ValueError: return {'status': 500, 'message':"Invalid Request"}, 500 + except BusinessException as exception: + return {'status': exception.status_code, 'message':exception.message}, 500 + +@cors_preflight('POST, DELETE, OPTIONS') +@API.route('/foirequests//ministryrequest//deleteoipc') +class FOIRequestsById(Resource): + """Creates a new version of foi request for iao users deleting all oipc details""" + @staticmethod + @TRACER.trace() + @cross_origin(origins=allowedorigins()) + @auth.require + def post(foirequestid,foiministryrequestid): + try: + current_foirequest = requestservice().getrequest(foirequestid, foiministryrequestid) + current_foirequest['isoipcreview'] = False + current_foirequest['oipcdetails'] = [] + foirequestschema = FOIRequestWrapperSchema().load(current_foirequest) + result = requestservice().saverequestversion(foirequestschema, foirequestid, foiministryrequestid,AuthHelper.getuserid()) + if result.success == True: + asyncio.ensure_future(eventservice().postevent(foiministryrequestid,"ministryrequest",AuthHelper.getuserid(),AuthHelper.getusername(),AuthHelper.isministrymember())) + metadata = json.dumps({"id": result.identifier, "ministries": result.args[0]}) + requestservice().posteventtoworkflow(foiministryrequestid, foirequestschema, json.loads(metadata),"iao") + return {'status': result.success, 'message':result.message,'id':result.identifier, 'ministryRequests': result.args[0]} , 200 + else: + return {'status': False, 'message':EXCEPTION_MESSAGE_NOTFOUND_REQUEST,'id':foirequestid} , 404 + except ValidationError as err: + return {'status': False, 'message': str(err)}, 400 + except KeyError as error: + return {'status': False, 'message': CUSTOM_KEYERROR_MESSAGE + str(error)}, 400 except BusinessException as exception: return {'status': exception.status_code, 'message':exception.message}, 500 \ No newline at end of file From d69d72f83d15fda9b86acae853ceec7f5db25269 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Wed, 13 Dec 2023 16:51:59 -0800 Subject: [PATCH 128/238] Reworked api endpoint - confirm with team to see which one is preferred --- .../request_api/resources/foirequest.py | 69 ++++++++++--------- 1 file changed, 38 insertions(+), 31 deletions(-) diff --git a/request-management-api/request_api/resources/foirequest.py b/request-management-api/request_api/resources/foirequest.py index 991853602..23fb4d0d8 100644 --- a/request-management-api/request_api/resources/foirequest.py +++ b/request-management-api/request_api/resources/foirequest.py @@ -126,6 +126,7 @@ def post(): @cors_preflight('GET,POST,PUT,OPTIONS') @API.route('/foirequests//ministryrequest/') +@API.route('/foirequests//ministryrequest//') class FOIRequestsById(Resource): """Creates a new version of foi request for iao updates""" @@ -133,11 +134,17 @@ class FOIRequestsById(Resource): @TRACER.trace() @cross_origin(origins=allowedorigins()) @auth.require - def post(foirequestid,foiministryrequestid): + def post(foirequestid,foiministryrequestid,actiontype=None): """ POST Method for capturing FOI requests before processing""" try: - request_json = request.get_json() - foirequestschema = FOIRequestWrapperSchema().load(request_json) + if actiontype == "deleteoipc": + current_foirequest = requestservice().getrequest(foirequestid, foiministryrequestid) + current_foirequest['isoipcreview'] = False + current_foirequest['oipcdetails'] = [] + foirequestschema = FOIRequestWrapperSchema().load(current_foirequest) + else: + request_json = request.get_json() + foirequestschema = FOIRequestWrapperSchema().load(request_json) result = requestservice().saverequestversion(foirequestschema, foirequestid, foiministryrequestid,AuthHelper.getuserid()) if result.success == True: asyncio.ensure_future(eventservice().postevent(foiministryrequestid,"ministryrequest",AuthHelper.getuserid(),AuthHelper.getusername(),AuthHelper.isministrymember())) @@ -292,31 +299,31 @@ def get(ministryrequestid,usertype=None): except BusinessException as exception: return {'status': exception.status_code, 'message':exception.message}, 500 -@cors_preflight('POST, DELETE, OPTIONS') -@API.route('/foirequests//ministryrequest//deleteoipc') -class FOIRequestsById(Resource): - """Creates a new version of foi request for iao users deleting all oipc details""" - @staticmethod - @TRACER.trace() - @cross_origin(origins=allowedorigins()) - @auth.require - def post(foirequestid,foiministryrequestid): - try: - current_foirequest = requestservice().getrequest(foirequestid, foiministryrequestid) - current_foirequest['isoipcreview'] = False - current_foirequest['oipcdetails'] = [] - foirequestschema = FOIRequestWrapperSchema().load(current_foirequest) - result = requestservice().saverequestversion(foirequestschema, foirequestid, foiministryrequestid,AuthHelper.getuserid()) - if result.success == True: - asyncio.ensure_future(eventservice().postevent(foiministryrequestid,"ministryrequest",AuthHelper.getuserid(),AuthHelper.getusername(),AuthHelper.isministrymember())) - metadata = json.dumps({"id": result.identifier, "ministries": result.args[0]}) - requestservice().posteventtoworkflow(foiministryrequestid, foirequestschema, json.loads(metadata),"iao") - return {'status': result.success, 'message':result.message,'id':result.identifier, 'ministryRequests': result.args[0]} , 200 - else: - return {'status': False, 'message':EXCEPTION_MESSAGE_NOTFOUND_REQUEST,'id':foirequestid} , 404 - except ValidationError as err: - return {'status': False, 'message': str(err)}, 400 - except KeyError as error: - return {'status': False, 'message': CUSTOM_KEYERROR_MESSAGE + str(error)}, 400 - except BusinessException as exception: - return {'status': exception.status_code, 'message':exception.message}, 500 \ No newline at end of file +# @cors_preflight('POST, DELETE, OPTIONS') +# @API.route('/foirequests//ministryrequest//deleteoipc') +# class FOIRequestsById(Resource): +# """Creates a new version of foi request for iao users deleting all oipc details""" +# @staticmethod +# @TRACER.trace() +# @cross_origin(origins=allowedorigins()) +# @auth.require +# def post(foirequestid,foiministryrequestid): +# try: +# current_foirequest = requestservice().getrequest(foirequestid, foiministryrequestid) +# current_foirequest['isoipcreview'] = False +# current_foirequest['oipcdetails'] = [] +# foirequestschema = FOIRequestWrapperSchema().load(current_foirequest) +# result = requestservice().saverequestversion(foirequestschema, foirequestid, foiministryrequestid,AuthHelper.getuserid()) +# if result.success == True: +# asyncio.ensure_future(eventservice().postevent(foiministryrequestid,"ministryrequest",AuthHelper.getuserid(),AuthHelper.getusername(),AuthHelper.isministrymember())) +# metadata = json.dumps({"id": result.identifier, "ministries": result.args[0]}) +# requestservice().posteventtoworkflow(foiministryrequestid, foirequestschema, json.loads(metadata),"iao") +# return {'status': result.success, 'message':result.message,'id':result.identifier, 'ministryRequests': result.args[0]} , 200 +# else: +# return {'status': False, 'message':EXCEPTION_MESSAGE_NOTFOUND_REQUEST,'id':foirequestid} , 404 +# except ValidationError as err: +# return {'status': False, 'message': str(err)}, 400 +# except KeyError as error: +# return {'status': False, 'message': CUSTOM_KEYERROR_MESSAGE + str(error)}, 400 +# except BusinessException as exception: +# return {'status': exception.status_code, 'message':exception.message}, 500 \ No newline at end of file From 07cb8443ee5d5e5559424bb5a201286e287205ab Mon Sep 17 00:00:00 2001 From: Richard Qi Date: Thu, 14 Dec 2023 13:37:54 -0800 Subject: [PATCH 129/238] 1. update version to 1 2. prepare return values --- .../59a97f42b5f2_add_version_to_applicant.py | 5 ++- .../models/FOIRequestApplicantMappings.py | 16 ++----- .../models/FOIRequestApplicants.py | 16 +------ .../request_api/services/applicantservice.py | 42 ++++++++++--------- 4 files changed, 31 insertions(+), 48 deletions(-) diff --git a/request-management-api/migrations/versions/59a97f42b5f2_add_version_to_applicant.py b/request-management-api/migrations/versions/59a97f42b5f2_add_version_to_applicant.py index d3abe9199..9fd31fafb 100644 --- a/request-management-api/migrations/versions/59a97f42b5f2_add_version_to_applicant.py +++ b/request-management-api/migrations/versions/59a97f42b5f2_add_version_to_applicant.py @@ -18,8 +18,11 @@ def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.add_column('FOIRequestApplicants', sa.Column('version', sa.Integer(), nullable=True)) + op.add_column('FOIRequestApplicants', sa.Column('version', sa.Integer(), nullable=True, default=1)) op.add_column('FOIRequestApplicantMappings', sa.Column('foirequestapplicant_version', sa.Integer(), nullable=True)) + + op.execute('Update public."FOIRequestApplicants" set version = 1;') + op.execute('Update public."FOIRequestApplicantMappings" set foirequestapplicant_version = 1;') # ### end Alembic commands ### diff --git a/request-management-api/request_api/models/FOIRequestApplicantMappings.py b/request-management-api/request_api/models/FOIRequestApplicantMappings.py index a2d284a36..782a702ec 100644 --- a/request-management-api/request_api/models/FOIRequestApplicantMappings.py +++ b/request-management-api/request_api/models/FOIRequestApplicantMappings.py @@ -42,19 +42,9 @@ class FOIRequestApplicantMapping(db.Model): def getrequestapplicants(cls,foirequest_id,foirequestversion): from .FOIRequestApplicants import FOIRequestApplicant requestapplicant_schema = FOIRequestApplicantMappingSchema(many=True) - _applicantinfos = db.session.query(FOIRequestApplicantMapping - ).join( - FOIRequestApplicant, - and_( - FOIRequestApplicant.foirequestapplicantid == FOIRequestApplicantMapping.foirequestapplicantid, - or_( - FOIRequestApplicant.version == FOIRequestApplicantMapping.foirequestapplicant_version, - FOIRequestApplicantMapping.foirequestapplicant_version is None - ) - ) - ).filter( - FOIRequestApplicantMapping.foirequest_id == foirequest_id, - FOIRequestApplicantMapping.foirequestversion_id == foirequestversion + _applicantinfos = db.session.query(FOIRequestApplicantMapping).filter( + FOIRequestApplicantMapping.foirequest_id == foirequest_id, + FOIRequestApplicantMapping.foirequestversion_id == foirequestversion ).order_by(FOIRequestApplicantMapping.foirequestapplicantmappingid.asc()).all() applicantinfos = requestapplicant_schema.dump(_applicantinfos) return applicantinfos diff --git a/request-management-api/request_api/models/FOIRequestApplicants.py b/request-management-api/request_api/models/FOIRequestApplicants.py index edf66e47d..409debee6 100644 --- a/request-management-api/request_api/models/FOIRequestApplicants.py +++ b/request-management-api/request_api/models/FOIRequestApplicants.py @@ -136,11 +136,7 @@ def getapplicantbyemail(cls, email): # FOIRequestApplicant.foirequestapplicantid == FOIRequestApplicantMapping.foirequestapplicantid and_( FOIRequestApplicant.foirequestapplicantid == FOIRequestApplicantMapping.foirequestapplicantid, - or_( - FOIRequestApplicant.version == None, - FOIRequestApplicantMapping.foirequestapplicant_version == None, - FOIRequestApplicant.version == FOIRequestApplicantMapping.foirequestapplicant_version - ) + FOIRequestApplicant.version == FOIRequestApplicantMapping.foirequestapplicant_version ) ).join( ApplicantCategory, @@ -237,8 +233,6 @@ def getapplicantbyemail(cls, email): contactemail.contactinformation == email ).order_by(FOIRequest.foirequestid.asc()) - print("query: ", query) - # print("result: ", query.all()) return applicantprofile_schema.dump(query.all()) @@ -311,11 +305,7 @@ def searchapplicant(cls, keywords): # FOIRequestApplicant.foirequestapplicantid == FOIRequestApplicantMapping.foirequestapplicantid and_( FOIRequestApplicant.foirequestapplicantid == FOIRequestApplicantMapping.foirequestapplicantid, - or_( - FOIRequestApplicant.version == None, - FOIRequestApplicantMapping.foirequestapplicant_version == None, - FOIRequestApplicant.version == FOIRequestApplicantMapping.foirequestapplicant_version - ) + FOIRequestApplicant.version == FOIRequestApplicantMapping.foirequestapplicant_version ) ).join( ApplicantCategory, @@ -413,8 +403,6 @@ def searchapplicant(cls, keywords): or_(*FOIRequestApplicant.getsearchfilters(keywords, contactemail, contacthomephone, contactworkphone, contactworkphone2, contactmobilephone)) ).order_by(FOIRequest.foirequestid.asc()) - # print("query: ", query) - # print("result: ", query.all()) return applicantprofile_schema.dump(query.all()) diff --git a/request-management-api/request_api/services/applicantservice.py b/request-management-api/request_api/services/applicantservice.py index 59c890f28..55cd1730a 100644 --- a/request-management-api/request_api/services/applicantservice.py +++ b/request-management-api/request_api/services/applicantservice.py @@ -40,29 +40,31 @@ def __transformfilteringfields(self, filterfields): def __prepareapplicant(self, applicant): return { - 'foirequestapplicantid': applicant["foirequestapplicantid"], - 'firstname': applicant["firstname"], - 'middlename': applicant["middlename"], - 'lastname': applicant["lastname"], - 'alsoknownas': applicant["alsoknownas"], - 'dob' : applicant["dob"], + 'additionalPersonalInfo': { + 'alsoKnownAs': applicant["alsoknownas"], + 'birthDate': applicant["dob"], + 'personalHealthNumber': applicant["phn"], + }, + 'foiRequestApplicantID': applicant["foirequestapplicantid"], + 'firstName': applicant["firstname"], + 'middleName': applicant["middlename"], + 'lastName': applicant["lastname"], #'createdat' : self.__formatedate(applicant["createdat)"], - 'businessname': applicant["businessname"], + 'businessName': applicant["businessname"], # 'applicant': applicant["applicant"], - 'applicantversion': applicant["applicantversion"], - 'foirequestid': applicant["foirequestid"], - 'foirequestversion': applicant["foirequestversion"], - 'requesttype': applicant["requesttype"], - 'applicantcategory': applicant["applicantcategory"], + 'applicantVersion': applicant["applicantversion"], + 'foirequestID': applicant["foirequestid"], + 'foirequestVersion': applicant["foirequestversion"], + 'requestType': applicant["requesttype"], + 'category': applicant["applicantcategory"], 'email':applicant["email"], 'address': applicant["address"], - 'homephone': applicant["homephone"], - 'workphone': applicant["workphone"], - 'workphone2': applicant["workphone2"], - 'mobilephone': applicant["mobilephone"], - 'othercontactinfo':applicant["othercontactinfo"], - 'employeenumber': applicant["employeenumber"], - 'correctionnumber': applicant["correctionnumber"], - 'phn':applicant["phn"] + 'phonePrimary': applicant["homephone"], + 'workPhonePrimary': applicant["workphone"], + 'workPhoneSecondary': applicant["workphone2"], + 'phoneSecondary': applicant["mobilephone"], + 'otherContactInfo':applicant["othercontactinfo"], + 'publicServiceEmployeeNumber': applicant["employeenumber"], + 'correctionalServiceNumber': applicant["correctionnumber"], } \ No newline at end of file From 3e6abf63d08966ac6b0f9b5c53fd3cce9d703b21 Mon Sep 17 00:00:00 2001 From: Richard Qi Date: Thu, 14 Dec 2023 14:57:38 -0800 Subject: [PATCH 130/238] uncomment auth --- .../request_api/resources/foiapplicant.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/request-management-api/request_api/resources/foiapplicant.py b/request-management-api/request_api/resources/foiapplicant.py index 20142b4fd..682db49a1 100644 --- a/request-management-api/request_api/resources/foiapplicant.py +++ b/request-management-api/request_api/resources/foiapplicant.py @@ -45,8 +45,8 @@ class FOIApplicants(Resource): @staticmethod @TRACER.trace() @cross_origin(origins=allowedorigins()) - # @auth.require - # @auth.isiao + @auth.require + @auth.isiao @cors_preflight('GET,OPTIONS') def get(email=None): print(email) @@ -72,8 +72,8 @@ class EventPagination(Resource): @staticmethod @TRACER.trace() @cross_origin(origins=allowedorigins()) - # @auth.require - # @auth.isiao + @auth.require + @auth.isiao @cors_preflight('GET,OPTIONS') def get(): try: From 40c149142e61daf157519730c918ca8e0a9a4867 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 14 Dec 2023 14:58:43 -0800 Subject: [PATCH 131/238] initial commit for front end of applicant profile --- forms-flow-web/package.json | 1 + .../src/actions/FOI/foiActionConstants.js | 2 + .../src/actions/FOI/foiRequestActions.js | 6 + .../services/FOI/foiRequestServices.js | 91 +++ .../components/FOI/FOIAuthenticateRouting.jsx | 19 +- .../FOIRequest/AdditionalApplicantDetails.js | 4 +- .../FOI/FOIRequest/AddressContanctInfo.js | 26 +- .../FOI/FOIRequest/ApplicantDetails.js | 12 +- .../FOI/FOIRequest/ApplicantProfileModal.js | 552 ++++++++++++++++++ .../components/FOI/FOIRequest/FOIRequest.js | 44 +- .../components/FOI/FOIRequest/foirequest.scss | 38 ++ forms-flow-web/src/constants/constants.js | 2 +- .../src/modules/FOI/foiRequestsReducer.js | 2 + .../request_api/schemas/foirequestwrapper.py | 2 + .../foirequest/requestservicecreate.py | 35 +- 15 files changed, 802 insertions(+), 34 deletions(-) create mode 100644 forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js diff --git a/forms-flow-web/package.json b/forms-flow-web/package.json index 48573e06b..68168c50b 100644 --- a/forms-flow-web/package.json +++ b/forms-flow-web/package.json @@ -90,6 +90,7 @@ "react-helmet": "^6.1.0", "react-js-pagination": "^3.0.3", "react-loading-overlay": "^1.0.1", + "react-modal-resizable-draggable": "^0.1.6", "react-quill": "^1.3.5", "react-redux": "^7.2.4", "react-router-dom": "^5.1.2", diff --git a/forms-flow-web/src/actions/FOI/foiActionConstants.js b/forms-flow-web/src/actions/FOI/foiActionConstants.js index beaca7433..a4de0c74d 100644 --- a/forms-flow-web/src/actions/FOI/foiActionConstants.js +++ b/forms-flow-web/src/actions/FOI/foiActionConstants.js @@ -36,6 +36,8 @@ const FOI_ACTION_CONSTANTS = { CLEAR_MINISTRYVIEWREQUEST_DETAILS: "CLEAR_MINISTRYVIEWREQUEST_DETAILS", FOI_REQUEST_DUE_DATE: "FOI_REQUEST_DUE_DATE", + FOI_REQUEST_APPLICANT_PROFILE: "FOI_REQUEST_APPLICANT_PROFILE", + FOI_IS_REQUEST_UPDATED: "FOI_IS_REQUEST_UPDATED", FOI_REQUEST_DESCRIPTION_HISTORY: "FOI_REQUEST_DESCRIPTION_HISTORY", FOI_MINISTRY_REQUESTSLIST: "FOI_MINISTRY_REQUESTSLIST", diff --git a/forms-flow-web/src/actions/FOI/foiRequestActions.js b/forms-flow-web/src/actions/FOI/foiRequestActions.js index 8cb6826c1..2239937c5 100644 --- a/forms-flow-web/src/actions/FOI/foiRequestActions.js +++ b/forms-flow-web/src/actions/FOI/foiRequestActions.js @@ -128,6 +128,12 @@ export const setFOIMinistryViewRequestDetail = (data) => (dispatch) => { payload: data, }); }; +export const setFOIRequestApplicantProfile = (data) => (dispatch) => { + dispatch({ + type: FOI_ACTION_CONSTANTS.FOI_REQUEST_APPLICANT_PROFILE, + payload: data, + }); +}; export const setFOIPDFStitchedRecordForHarms = (data) => (dispatch) => { dispatch({ type: FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_RECORD_FOR_HARMS, diff --git a/forms-flow-web/src/apiManager/services/FOI/foiRequestServices.js b/forms-flow-web/src/apiManager/services/FOI/foiRequestServices.js index 30bd94e36..6ad3fcb6f 100644 --- a/forms-flow-web/src/apiManager/services/FOI/foiRequestServices.js +++ b/forms-flow-web/src/apiManager/services/FOI/foiRequestServices.js @@ -527,3 +527,94 @@ export const fetchRestrictedRequestCommentTagList = (requestid, ministryId, ...r } }; +export const fetchPotentialApplicants = async (firstname, lastname, email, phone, ...rest) => { + console.log("fetch applicants" + firstname) + console.log(firstname) + console.log(lastname) + + const done = fnDone(rest); + await new Promise(resolve => {setTimeout(resolve, 3000)}); + done(null, [ + { id: 1, lastName: 'Snow', firstName: 'Jon', age: 35 }, + { id: 2, lastName: 'Lannister', firstName: 'Cersei', age: 42 }, + { id: 3, lastName: 'Lannister', firstName: 'Jaime', age: 45 }, + { id: 4, lastName: 'Stark', firstName: 'Arya', age: 16 }, + { id: 5, lastName: 'Targaryen', firstName: 'Daenerys', age: null }, + { id: 7, lastName: 'Clifford', firstName: 'Ferrara', age: 44 }, + { id: 8, lastName: 'Frances', firstName: 'Rossini', age: 36 }, + { id: 9, lastName: 'Roxie', firstName: 'Harvey', age: 65 }, + ]); + return; + // const apiUrlgetRequestDetails = replaceUrl(replaceUrl( + // API.FOI_MINISTRYVIEW_REQUEST_API, + // "", + // requestId + // ), "", ministryId); + // return (dispatch) => { + // httpGETRequest(apiUrlgetRequestDetails, {}, UserService.getToken()) + // .then((res) => { + // if (res.data) { + // const foiRequest = res.data; + // dispatch(clearMinistryViewRequestDetails({})); + // dispatch(setFOIMinistryViewRequestDetail(foiRequest)); + // dispatch(fetchFOIMinistryAssignedToList(foiRequest.selectedMinistries[0].code.toLowerCase())); + // dispatch(setFOILoader(false)); + // } else { + // dispatch(serviceActionError(res)); + // dispatch(setFOILoader(false)); + // throw new Error(`Error in fetching ministry request details for request# ${requestId} ministry# ${ministryId}`) + // } + // }) + // .catch((error) => { + // catchError(error, dispatch); + // }); + // }; +}; + +export const fetchApplicantInfo = async (firstname, ...rest) => { + + const done = fnDone(rest); + done(null, + { id: 1, lastName: 'Snow', firstName: 'Jon', age: 35, email: 'jon.snow@gmail.com', + additionalPersonalInfo: {birthDate: "2023-12-07"}, + requestHistory: [{requestId: "EDU-2023-234345", receivedDate: "2023-12-07", currentState: "Open", requestDescription: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but als"}] + } + ); + return; + // const apiUrlgetRequestDetails = replaceUrl(replaceUrl( + // API.FOI_MINISTRYVIEW_REQUEST_API, + // "", + // requestId + // ), "", ministryId); + // return (dispatch) => { + // httpGETRequest(apiUrlgetRequestDetails, {}, UserService.getToken()) + // .then((res) => { + // if (res.data) { + // const foiRequest = res.data; + // dispatch(clearMinistryViewRequestDetails({})); + // dispatch(setFOIMinistryViewRequestDetail(foiRequest)); + // dispatch(fetchFOIMinistryAssignedToList(foiRequest.selectedMinistries[0].code.toLowerCase())); + // dispatch(setFOILoader(false)); + // } else { + // dispatch(serviceActionError(res)); + // dispatch(setFOILoader(false)); + // throw new Error(`Error in fetching ministry request details for request# ${requestId} ministry# ${ministryId}`) + // } + // }) + // .catch((error) => { + // catchError(error, dispatch); + // }); + // }; +}; + +export const fetchApplicantContactHistory = (...rest) => { + const done = fnDone(rest); + done(null, + [{ + field: "Email", + value: "a@b.ca", + date: "2023-12-11", + username: "foiintake@idir", + }] + ); +} \ No newline at end of file diff --git a/forms-flow-web/src/components/FOI/FOIAuthenticateRouting.jsx b/forms-flow-web/src/components/FOI/FOIAuthenticateRouting.jsx index 8b3f3d346..8ad114ee7 100644 --- a/forms-flow-web/src/components/FOI/FOIAuthenticateRouting.jsx +++ b/forms-flow-web/src/components/FOI/FOIAuthenticateRouting.jsx @@ -1,4 +1,4 @@ -import React, {useEffect}from "react"; +import React, {useEffect, useState}from "react"; import { Redirect, Route } from "react-router-dom"; import { useDispatch, useSelector } from "react-redux"; import "semantic-ui-css/semantic.min.css"; @@ -15,12 +15,21 @@ import { isMinistryLogin } from '../../helper/FOI/helper'; import UnAuthorized from "./UnAuthorized"; import Admin from "./Admin"; import Divisions from "./Admin/Divisions"; +import ApplicantProfileModal from "./FOIRequest/ApplicantProfileModal"; const FOIAuthenticateRouting = React.memo((props) => { const dispatch = useDispatch(); const isAuth = useSelector((state) => state.user.isAuthenticated); + + const [applicantProfileModalOpen, setApplicantProfileModalOpen] = useState(false); + const handleApplicantModalClose = () => { + setApplicantProfileModalOpen(false); + } + const openApplicantProfileModal = () => { + setApplicantProfileModalOpen(true); + } useEffect(()=>{ console.log('authenticate') @@ -51,13 +60,13 @@ const FOIAuthenticateRouting = React.memo((props) => { } - + - + @@ -72,6 +81,10 @@ const FOIAuthenticateRouting = React.memo((props) => { + ) : ( diff --git a/forms-flow-web/src/components/FOI/FOIRequest/AdditionalApplicantDetails.js b/forms-flow-web/src/components/FOI/FOIRequest/AdditionalApplicantDetails.js index 3a1e1b4e5..b5c55b678 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/AdditionalApplicantDetails.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/AdditionalApplicantDetails.js @@ -10,7 +10,7 @@ import AccordionDetails from '@material-ui/core/AccordionDetails'; import Typography from '@material-ui/core/Typography'; import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; -const AdditionalApplicantDetails = React.memo(({requestDetails, createSaveRequestObject, disableInput}) => { +const AdditionalApplicantDetails = React.memo(({requestDetails, createSaveRequestObject, disableInput, defaultExpanded}) => { /** * Addition Applicant details box in the UI * No mandatory fields here @@ -126,7 +126,7 @@ const AdditionalApplicantDetails = React.memo(({requestDetails, createSaveReques return (
- + } id="additionalApplicantDetails-header"> ADDITIONAL APPLICANT DETAILS diff --git a/forms-flow-web/src/components/FOI/FOIRequest/AddressContanctInfo.js b/forms-flow-web/src/components/FOI/FOIRequest/AddressContanctInfo.js index db057edbd..451b26fc6 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/AddressContanctInfo.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/AddressContanctInfo.js @@ -9,7 +9,8 @@ import AccordionSummary from '@material-ui/core/AccordionSummary'; import AccordionDetails from '@material-ui/core/AccordionDetails'; import Typography from '@material-ui/core/Typography'; import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; -import {closeContactInfo} from '../FOIRequest/utils'; +import ApplicantProfileModal from "./ApplicantProfileModal"; +import { StateEnum } from "../../../constants/FOI/statusEnum"; const useStyles = makeStyles((_theme) => ({ row: { @@ -34,7 +35,8 @@ const AddressContactDetails = memo( handleContanctDetailsValue, handleEmailValidation, disableInput, - userDetail + defaultExpanded, + moreInfoAction, }) => { const classes = useStyles(); /** @@ -107,6 +109,13 @@ const AddressContactDetails = memo( //state management for email validation const [validation, setValidation] = React.useState({}); + // const [modalOpen, setModalOpen] = React.useState(false); + + + // const handleModalClose = () => { + // setModalOpen(false); + // } + React.useEffect(() => { setFieldValues(); const contanctDetailsObject = { @@ -289,12 +298,21 @@ const AddressContactDetails = memo( }; return (
- + } id="addressContactInfo-header"> ADDRESS AND CONTACT INFORMATION - + +
+ {moreInfoAction && } + {/* */} +
{ const useStyles = makeStyles({ @@ -227,11 +228,16 @@ const ApplicantDetails = React.memo( return (
- + } id="applicantDetails-header"> APPLICANT DETAILS +
+ {showHistory && } +
({ + root: { + "& .MuiTextField-root": { + margin: theme.spacing(1, "0px"), + }, + }, + disabledTitle: { + opacity: "0.3", + }, +})); + +const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { + const classes = useStyles(); + + let requestDetails = useSelector((state) => state.foiRequests.foiRequestDetail); + const dispatch = useDispatch(); + + console.log(requestDetails); + + const [searchText, setSearchText] = useState(""); + const [isLoading, setIsLoading] = useState(true); + const [rows, setRows] = useState([]); + const [selectedApplicant, setSelectedApplicant] = useState(false) + const [searchMode, setSearchMode] = useState("auto") + const [saveApplicantObject, setSaveApplicantObject] = React.useState({}) + const [showRequestHistory, setShowRequestHistory] = useState(false); + const [confirmationMessage, setConfirmationMessage] = useState(false); + const [createConfirmation, setCreateConfirmation] = useState(false); + const [isProfileDifferent, setIsProfileDifferent] = useState(false); + const [applicantHistory, setApplicantHistory] = useState(false); + + const columns = [ + { + field: 'firstName', + headerName: 'FIRST NAME', + flex: 1, + }, + { + field: 'middleName', + headerName: 'MIDDLE NAME', + flex: 1, + }, + { + field: 'lastName', + headerName: 'LAST NAME', + flex: 1, + }, + { + field: 'birthDate', + headerName: 'DATE OF BIRTH', + flex: 1, + }, + { + field: 'email', + headerName: 'EMAIL', + flex: 1, + }, + { + field: 'primaryPhone', + headerName: 'PRIMARY PHONE', + flex: 1, + }, + ]; + + + const requestHistoryColumns = [ + { + field: "requestId", + headerName: "REQUEST ID", + flex: 1, + }, + { + field: "currentState", + headerName: "CURRENT STATE", + flex: 1, + }, + { + field: "receivedDate", + headerName: "RECEIVED DATE", + flex: 1, + }, + { + field: "requestDescription", + headerName: "REQUEST DESRCIPTION", + flex: 3, + }, + ]; + + useEffect(() => { + if (modalOpen) { + setIsLoading(true); + if (requestDetails.currentState === StateEnum.intakeinprogress.name) { + fetchPotentialApplicants( + requestDetails.firstName, + requestDetails.lastName, + requestDetails.email, + requestDetails.primaryPhone, + (err, res) => { + setRows(res); + setIsLoading(false); + }) + } else { + fetchApplicantInfo(requestDetails.firstName, (err, res) => { + setSelectedApplicant(res); + }) + } + } + }, [modalOpen]) + + useEffect(() => { + setSaveApplicantObject({...selectedApplicant}) + for (let field in selectedApplicant) { + if (field === 'additionalPersonalInfo') { + if ((requestDetails[field][FOI_COMPONENT_CONSTANTS.DOB] && selectedApplicant[field][FOI_COMPONENT_CONSTANTS.DOB] !== requestDetails[field][FOI_COMPONENT_CONSTANTS.DOB]) || + (requestDetails[field][FOI_COMPONENT_CONSTANTS.PERSONAL_HEALTH_NUMBER] && selectedApplicant[field][FOI_COMPONENT_CONSTANTS.PERSONAL_HEALTH_NUMBER] !== requestDetails[field][FOI_COMPONENT_CONSTANTS.PERSONAL_HEALTH_NUMBER])) { + setIsProfileDifferent(true); + break; + } + } else if (requestDetails[field] && selectedApplicant[field] !== requestDetails[field]) { + setIsProfileDifferent(true); + break; + } + } + }, [selectedApplicant]) + + const createSaveApplicantObject = (name, value, value2) => { + let newApplicantObj = {...saveApplicantObject} + if ([FOI_COMPONENT_CONSTANTS.DOB, FOI_COMPONENT_CONSTANTS.PERSONAL_HEALTH_NUMBER].includes(name)) { + newApplicantObj.additionalPersonalInfo[name] = value; + } else { + newApplicantObj[name] = value; + } + setSaveApplicantObject(newApplicantObj) + } + + const selectApplicantRow = (e) => { + fetchApplicantInfo(e.firstName, (err, res) => { + setSelectedApplicant(res); + }) + } + + const handleClose = () => { + setSearchText(""); + setIsLoading(true); + setRows([]); + setSelectedApplicant(false); + setConfirmationMessage(false); + setShowRequestHistory(false); + setApplicantHistory(false); + setCreateConfirmation(false); + handleModalClose(); + } + + const search = (rows) => { + return rows.filter(r => (r.firstName.toLowerCase().indexOf(searchText.toLowerCase()) > -1) || + (r.middleName?.toLowerCase().indexOf(searchText.toLowerCase()) > -1) || + (r.lastName.toLowerCase().indexOf(searchText.toLowerCase()) > -1) || + (r.birthDate?.toLowerCase().indexOf(searchText.toLowerCase()) > -1) || + (r.email?.toLowerCase().indexOf(searchText.toLowerCase()) > -1) || + (r.primaryPhone?.toLowerCase().indexOf(searchText.toLowerCase()) > -1) + ) + } + + const onSearchChange = (e) => { + if (searchMode === 'auto') { + setSearchText(e.target.value) + } + } + + const onSearchEnter = (e) => { + if (searchMode === 'manual' && e.key === 'Enter') { + console.log("search"); + } + } + + const selectProfile = () => { + if (_.isEqual(selectedApplicant, saveApplicantObject) || confirmationMessage) { + if (requestDetails.currentState === StateEnum.intakeinprogress.name) { + saveApplicantObject.applicantprofileid = 1; // fill in with actual id later + dispatch(setFOIRequestApplicantProfile(saveApplicantObject)); + } + // call save info api + handleClose() + } else { + setConfirmationMessage(true); + } + } + + const copyInfo = () => { + let updatedApplicant = {...selectedApplicant} + for (let field in selectedApplicant) { + if (field === 'additionalPersonalInfo') { + for (let infofield in requestDetails[field]) { + if (requestDetails[field][infofield] !== selectedApplicant[field][infofield]) { + updatedApplicant[field][infofield] = requestDetails[field][infofield]; + } + } + } else if (requestDetails[field] && selectedApplicant[field] !== requestDetails[field]) { + updatedApplicant[field] = requestDetails[field]; + } + } + setSaveApplicantObject(updatedApplicant); + setIsProfileDifferent(false); + } + + const showApplicantHistory = () => { + fetchApplicantContactHistory((err, res) => { + setApplicantHistory(res); + }) + } + + const back = () => { + if (applicantHistory) { + setApplicantHistory(false); + } else { + setSelectedApplicant(false); + } + } + + const cancel = () => { + if (createConfirmation) { + setCreateConfirmation(false); + } else { + handleClose(); + } + } + + const createProfile = () => { + if (!createConfirmation) { + setCreateConfirmation(true); + } else { + handleClose(); + } + } + + + return ( +
+ + + {selectedApplicant ? +

+ setShowRequestHistory(false)} + disableRipple + className={clsx("request-history-header applicant-profile-header", { + [classes.disabledTitle]: showRequestHistory + })} + > + Applicant Profile + + + setShowRequestHistory(true)} + disableRipple + className={clsx("request-history-header applicant-profile-header", { + [classes.disabledTitle]: !showRequestHistory + })} + > + Request History ({selectedApplicant.requestHistory.length}) + +

+ : +

+ Search Applicants +

+ } + + Close + + +
+
+ + {selectedApplicant ? + confirmationMessage ? +
Are you sure you would like to save changes for all open requests?

Please ensure you have checked the Request History to see the request(s) that will be affected.
+ : + (showRequestHistory ? + <> + + 'auto'} + getRowId={(row) => row.requestId} + /> + + : + applicantHistory ? + <> + {applicantHistory.map((entry, index) => { + return ( + } + aria-controls="panel1a-content" + > + {`APPLICANT CONTACT DETAILS`} + {entry.username} - {entry.date} + + +
+
+ {entry.field}: {entry.value} +
+
+
+
) + })} + + : + <> + {isProfileDifferent && + + Some of the fields in this profile do not match your original request. + + + } + {}} + handleApplicantDetailsValue={() => {}} + disableInput={false} + defaultExpanded={true} + showHistory={showApplicantHistory} + /> + {}} + handleContanctDetailsValue={() => {}} + handleEmailValidation={() => {}} + disableInput={false} + defaultExpanded={false} + /> + + ) + : + createConfirmation ? +
New Profile will be created automatically when request is moved to open state.

Please make any additional changes in Request Details.
+ : + <> +
+ Select an applicant to view their details. Or create a new profile + if applicant cannot be found. +
+ + + + + Search + + + + } + fullWidth + /> + + + + setSearchMode("manual")} + clicked={searchMode === "manual"} + /> + setSearchMode("auto")} + clicked={searchMode === "auto"} + /> + + + + + + + + } +
+
+ + {selectedApplicant ? + (confirmationMessage ? + <> + : + <>{!applicantHistory && } + + ): + <> + + } + +
+
+ ); + }); + +export default ApplicantProfileModal; \ No newline at end of file diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index d754731d2..c6ad8617d 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -73,6 +73,8 @@ import { isMandatoryField, isAxisSyncDisplayField, getUniqueIdentifier, + closeContactInfo, + closeApplicantDetails } from "./utils"; import { ConditionalComponent, @@ -89,6 +91,8 @@ import { UnsavedModal } from "../customComponents"; import { DISABLE_GATHERINGRECORDS_TAB } from "../../../constants/constants"; import _ from "lodash"; import { MinistryNeedsScanning } from "../../../constants/FOI/enum"; +import ApplicantProfileModal from "./ApplicantProfileModal"; +import { setFOIRequestDetail } from "../../../actions/FOI/foiRequestActions"; const useStyles = makeStyles((theme) => ({ root: { @@ -112,7 +116,7 @@ const useStyles = makeStyles((theme) => ({ }, })); -const FOIRequest = React.memo(({ userDetail }) => { +const FOIRequest = React.memo(({ userDetail, openApplicantProfileModal }) => { const [_requestStatus, setRequestStatus] = React.useState( StateEnum.unopened.name ); @@ -154,6 +158,9 @@ const FOIRequest = React.memo(({ userDetail }) => { // let requestRecords = useSelector( // (state) => state.foiRequests.foiRequestRecords // ); + let requestApplicantProfile = useSelector( + (state) => state.foiRequests.foiRequestApplicantProfile + ) const [attachments, setAttachments] = useState(requestAttachments); const [comment, setComment] = useState([]); const [requestState, setRequestState] = useState(StateEnum.unopened.name); @@ -170,6 +177,8 @@ const FOIRequest = React.memo(({ userDetail }) => { dispatch(push(`/foi/dashboard`)); }; + + const returnToQueue = (e) => { if (unSavedRequest) { setUnsavedMessage( @@ -281,7 +290,9 @@ const FOIRequest = React.memo(({ userDetail }) => { dispatch(fetchApplicantCorrespondenceTemplates()); dispatch( fetchRedactedSections(ministryId, (_err, res) => { - setRedactedSections(res.sections); + if (!_err) { + setRedactedSections(res.sections); + } }) ); } @@ -327,6 +338,23 @@ const FOIRequest = React.memo(({ userDetail }) => { } }, [requestDetails]); + useEffect(() => { + if (requestApplicantProfile) { + let newRequestDetails = { ...saveRequestObject }; + for (let field in requestApplicantProfile) { + if (field === "additionalPersonalInfo") { + for (let infofield in requestApplicantProfile[field]) { + newRequestDetails[field][infofield] = + requestApplicantProfile[field][infofield]; + } + } else { + newRequestDetails[field] = requestApplicantProfile[field]; + } + } + dispatch(setFOIRequestDetail(newRequestDetails)) + } + }, [requestApplicantProfile]); + useEffect(() => { if (isIAORestricted) dispatch(fetchRestrictedRequestCommentTagList(requestId, ministryId)); @@ -1118,8 +1146,8 @@ const FOIRequest = React.memo(({ userDetail }) => { handleApplicantDetailsValue } createSaveRequestObject={createSaveRequestObject} - disableInput={disableInput} - userDetail={userDetail} + disableInput={disableInput || ministryId} + defaultExpanded={!closeApplicantDetails(userDetail, requestDetails?.requestType)} /> {requiredRequestDetailsValues.requestType.toLowerCase() === FOI_COMPONENT_CONSTANTS.REQUEST_TYPE_PERSONAL && ( @@ -1151,9 +1179,10 @@ const FOIRequest = React.memo(({ userDetail }) => { handleContactDetailsInitialValue } handleContanctDetailsValue={handleContanctDetailsValue} - disableInput={disableInput} + disableInput={disableInput || ministryId} handleEmailValidation={handleEmailValidation} - userDetail={userDetail} + defaultExpanded={!closeContactInfo(userDetail,requestDetails)} + moreInfoAction={openApplicantProfileModal} /> { )} {showDivisionalTracking && ( diff --git a/forms-flow-web/src/components/FOI/FOIRequest/foirequest.scss b/forms-flow-web/src/components/FOI/FOIRequest/foirequest.scss index 5a4bcc002..d05c931b4 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/foirequest.scss +++ b/forms-flow-web/src/components/FOI/FOIRequest/foirequest.scss @@ -164,4 +164,42 @@ height: fit-content; .foi-details-row-break { margin-bottom: 2em; +} + +.applicant-profile-modal { + z-index: 2000 !important; +} + +.search-applicants-header { + margin-left: 22px !important; +} + +.applicant-profile-header{ + font-size: 25px !important; + color: black; +} + +.flexible-modal-drag-area { + background: none !important; +} + +.flexible-modal-resizer { + position:absolute; + right:0; + bottom:0; + cursor:se-resize; + margin:5px; + border-bottom: none !important; + border-right: none !important; + background-size: 16px; + background-image: url("data:image/svg+xml,%3Csvg width='30' height='30' xmlns='http://www.w3.org/2000/svg' stroke='null' style='vector-effect: non-scaling-stroke;'%3E%3Cg id='Layer_1'%3E%3Ctitle%3ELayer 1%3C/title%3E%3Cellipse stroke='%23666666' ry='0.44882' rx='0.44882' id='svg_2' cy='28.93701' cx='18.62205' fill='none'/%3E%3Cellipse stroke='%23666666' ry='0.44882' rx='0.44882' id='svg_3' cy='19.01575' cx='28.38583' fill='none'/%3E%3Cline transform='rotate(45 23.4602 24.0105)' id='svg_4' y2='31.01042' x2='23.51658' y1='17.01051' x1='23.40384' stroke-width='2' stroke='%23666666' fill='none'/%3E%3Cline transform='rotate(45 19.7988 19.5616)' stroke='%23666666' id='svg_6' y2='32.63046' x2='19.85521' y1='6.49282' x1='19.74247' stroke-width='2' fill='none'/%3E%3Cellipse stroke='%23666666' ry='0.44882' rx='0.44882' id='svg_7' cy='10.27559' cx='28.93701' fill='none'/%3E%3Cellipse stroke='%23666666' ry='0.44882' rx='0.44882' id='svg_8' cy='28.77953' cx='10.66929' fill='none'/%3E%3Cline transform='rotate(45 15.4681 15.4671)' stroke='%23666666' id='svg_9' y2='34.10369' x2='15.52444' y1='-3.16948' x1='15.41171' stroke-width='2' fill='none'/%3E%3Cellipse stroke='%23666666' ry='0.44882' rx='0.44882' id='svg_10' cy='2.24409' cx='28.62205' fill='none'/%3E%3Cellipse stroke='%23666666' ry='0.44882' rx='0.44882' id='svg_11' cy='28.62205' cx='2.40158' fill='none'/%3E%3C/g%3E%3C/svg%3E"); +} + +#menu- { + z-index: 2300 !important; +} + +.btn-update-profile { + border: none; + background: none; } \ No newline at end of file diff --git a/forms-flow-web/src/constants/constants.js b/forms-flow-web/src/constants/constants.js index ab289438e..3a19df993 100644 --- a/forms-flow-web/src/constants/constants.js +++ b/forms-flow-web/src/constants/constants.js @@ -62,6 +62,6 @@ export const FOI_RECORD_FORMATS = `${(window._env_ && window._env_.REACT_APP_FOI export const RECORD_PROCESSING_HRS = (window._env_ && window._env_.REACT_APP_RECORD_PROCESSING_HRS) || process.env.REACT_APP_RECORD_PROCESSING_HRS || 4; -export const DISABLE_REDACT_WEBLINK = (window._env_ && window._env_.REACT_APP_DISABLE_REDACT_WEBLINK) || process.env.REACT_APP_DISABLE_REDACT_WEBLINK || false; +export const DISABLE_REDACT_WEBLINK = (window._env_ && window._env_.REACT_APP_DISABLE_REDACT_WEBLINK) || process.env.REACT_APP_DISABLE_REDACT_WEBLINK || 'false'; export const DISABLE_GATHERINGRECORDS_TAB = (window._env_ && window._env_.REACT_APP_DISABLE_GATHERINGRECORDS_TAB) || process.env.REACT_APP_DISABLE_GATHERINGRECORDS_TAB || 'false'; diff --git a/forms-flow-web/src/modules/FOI/foiRequestsReducer.js b/forms-flow-web/src/modules/FOI/foiRequestsReducer.js index 8dd27296b..3f2b3dc1a 100644 --- a/forms-flow-web/src/modules/FOI/foiRequestsReducer.js +++ b/forms-flow-web/src/modules/FOI/foiRequestsReducer.js @@ -201,6 +201,8 @@ const foiRequests = (state = initialState, action) => { return { ...state, foiRequestsCount: action.payload.count }; case FOI_ACTION_CONSTANTS.FOI_REQUEST_DETAIL: return { ...state, foiRequestDetail: action.payload }; + case FOI_ACTION_CONSTANTS.FOI_REQUEST_APPLICANT_PROFILE: + return { ...state, foiRequestApplicantProfile: action.payload }; case FOI_ACTION_CONSTANTS.FOI_REQUEST_DUE_DATE: return { ...state, diff --git a/request-management-api/request_api/schemas/foirequestwrapper.py b/request-management-api/request_api/schemas/foirequestwrapper.py index efdb027ac..5e829c84c 100644 --- a/request-management-api/request_api/schemas/foirequestwrapper.py +++ b/request-management-api/request_api/schemas/foirequestwrapper.py @@ -110,6 +110,8 @@ class Meta: # pylint: disable=too-few-public-methods correctionalServiceNumber = fields.Str(data_key="correctionalServiceNumber",allow_none=True, validate=[validate.Length(max=50, error=MAX_EXCEPTION_MESSAGE)]) publicServiceEmployeeNumber = fields.Str(data_key="publicServiceEmployeeNumber",allow_none=True, validate=[validate.Length(max=50, error=MAX_EXCEPTION_MESSAGE)]) isiaorestricted = fields.Bool(data_key="isiaorestricted") + + applicantprofileid = fields.Int(data_key="applicantprofileid",required=False,allow_none=True) selectedMinistries = fields.Nested(FOIMinistryRequestWrapperSchema, many=True) additionalPersonalInfo = fields.Nested(FOIAdditionallPersonalInfoWrapperSchema,required=False,allow_none=True) diff --git a/request-management-api/request_api/services/foirequest/requestservicecreate.py b/request-management-api/request_api/services/foirequest/requestservicecreate.py index 6d4b2142f..555c8570e 100644 --- a/request-management-api/request_api/services/foirequest/requestservicecreate.py +++ b/request-management-api/request_api/services/foirequest/requestservicecreate.py @@ -12,6 +12,7 @@ from request_api.models.FOIRequestContactInformation import FOIRequestContactInformation from request_api.models.FOIRequestPersonalAttributes import FOIRequestPersonalAttribute from request_api.models.FOIRequestApplicantMappings import FOIRequestApplicantMapping +from request_api.models.RequestorType import RequestorType import json class requestservicecreate: @@ -126,20 +127,26 @@ def __prepareapplicants(self, foirequestschema, userid): requestapplicantarr = [] selfalsoknownas=None selfdob=None - if foirequestschema.get("additionalPersonalInfo") is not None: - applicantinfo = foirequestschema.get("additionalPersonalInfo") - selfdob = applicantinfo["birthDate"] if requestservicebuilder().isNotBlankorNone(foirequestschema,"birthDate","additionalPersonalInfo") else None - selfalsoknownas = applicantinfo["alsoKnownAs"] if requestservicebuilder().isNotBlankorNone(foirequestschema,"alsoKnownAs","additionalPersonalInfo") else None - requestapplicantarr.append( - requestservicebuilder().createapplicant(foirequestschema.get("firstName"), - foirequestschema.get("lastName"), - "Self", - userid, - foirequestschema.get("middleName"), - foirequestschema.get("businessName"), - selfalsoknownas, - selfdob) - ) + if foirequestschema.get("additionalPersonalInfo") is not None and foirequestschema.get('requeststatusid') == 1: + if foirequestschema.get('applicantprofileid', None): + requestapplicant = FOIRequestApplicantMapping() + requestapplicant.foirequestapplicantid = foirequestschema['applicantprofileid'] + requestapplicant.requestortypeid = RequestorType().getrequestortype("Self")["requestortypeid"] + requestapplicantarr.append(requestapplicant) + else: + applicantinfo = foirequestschema.get("additionalPersonalInfo") + selfdob = applicantinfo["birthDate"] if requestservicebuilder().isNotBlankorNone(foirequestschema,"birthDate","additionalPersonalInfo") else None + selfalsoknownas = applicantinfo["alsoKnownAs"] if requestservicebuilder().isNotBlankorNone(foirequestschema,"alsoKnownAs","additionalPersonalInfo") else None + requestapplicantarr.append( + requestservicebuilder().createapplicant(foirequestschema.get("firstName"), + foirequestschema.get("lastName"), + "Self", + userid, + foirequestschema.get("middleName"), + foirequestschema.get("businessName"), + selfalsoknownas, + selfdob) + ) #Prepare additional applicants if foirequestschema.get("additionalPersonalInfo") is not None: From 31ffc19459893208e8e00e9bda68692b7aef214a Mon Sep 17 00:00:00 2001 From: Richard Qi Date: Thu, 14 Dec 2023 15:13:07 -0800 Subject: [PATCH 132/238] bug fix --- request-management-api/request_api/auth.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/request-management-api/request_api/auth.py b/request-management-api/request_api/auth.py index 386b68e03..ff89ca2c9 100644 --- a/request-management-api/request_api/auth.py +++ b/request-management-api/request_api/auth.py @@ -148,10 +148,10 @@ def wrapper(*args, **kwargs): @classmethod def isiao(cls,func): @wraps(func) - def decorated(type, id, field,*args, **kwargs): + def decorated(*args, **kwargs): usertype = AuthHelper.getusertype() if(usertype == "iao"): - return func(type, id, field,*args, **kwargs) + return func(*args, **kwargs) else: return "Unauthorized" , 401 return decorated From 775ea76c3da17f0a7bf45672e6729fcacfe2037f Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Thu, 14 Dec 2023 16:46:37 -0800 Subject: [PATCH 133/238] Adjusted model method getstatehistory to incl created_at times --- .../request_api/models/FOIMinistryRequests.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index dc25bc8ac..0c43b1538 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -257,13 +257,13 @@ def getstatesummary(cls, ministryrequestid): sql =select status, version from (select distinct name as status, version from "FOIMinistryRequests" fm inner join "FOIRequestStatuses" fs2 on fm.requeststatusid = fs2.requeststatusid where foiministryrequestid=:ministryrequestid order by version asc) as fs3 order by version desc; """ - sql = """select fm2.version, fs2."name" as status from "FOIMinistryRequests" fm2 inner join "FOIRequestStatuses" fs2 on fm2.requeststatusid = fs2.requeststatusid + sql = """select fm2.version, fs2."name" as status, fm2.created_at from "FOIMinistryRequests" fm2 inner join "FOIRequestStatuses" fs2 on fm2.requeststatusid = fs2.requeststatusid where fm2.foiministryrequestid=:ministryrequestid order by version desc""" rs = db.session.execute(text(sql), {'ministryrequestid': ministryrequestid}) _tmp_state = None for row in rs: if row["status"] != _tmp_state: - transitions.append({"status": row["status"], "version": row["version"]}) + transitions.append({"status": row["status"], "version": row["version"], "created_at": row["created_at"]}) _tmp_state = row["status"] except Exception as ex: logging.error(ex) From cb68be15cd11b000afb44bd90fbbf42e6b8be71e Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Fri, 15 Dec 2023 11:58:00 -0800 Subject: [PATCH 134/238] Endpoint reworked. A new endpoint for specific sections of FOI Requests being chnaged by iao users created --- .../src/apiManager/endpoints/index.js | 1 + .../services/FOI/foiRequestServices.js | 4 +- .../components/FOI/FOIRequest/FOIRequest.js | 3 - .../request_api/resources/foirequest.py | 71 +++++++++---------- 4 files changed, 36 insertions(+), 43 deletions(-) diff --git a/forms-flow-web/src/apiManager/endpoints/index.js b/forms-flow-web/src/apiManager/endpoints/index.js index 9e2ddb7d7..fd9939a87 100644 --- a/forms-flow-web/src/apiManager/endpoints/index.js +++ b/forms-flow-web/src/apiManager/endpoints/index.js @@ -25,6 +25,7 @@ const API = { FOI_GET_RECEIVED_MODELIST: `${FOI_BASE_API_URL}/api/foiflow/receivedmodes`, FOI_POST_REQUEST_POST: `${FOI_BASE_API_URL}/api/foirequests`, FOI_REQUEST_API: `${FOI_BASE_API_URL}/api/foirequests//ministryrequest/`, + FOI_REQUEST_SECTION_API: `${FOI_BASE_API_URL}/api/foirequests//ministryrequest//section`, FOI_MINISTRYVIEW_REQUEST_API: `${FOI_BASE_API_URL}/api/foirequests//ministryrequest//ministry`, FOI_RAW_REQUEST_DESCRIPTION: `${FOI_BASE_API_URL}/api/foiaudit/rawrequest//description`, FOI_MINISTRY_REQUEST_DESCRIPTION: `${FOI_BASE_API_URL}/api/foiaudit/ministryrequest//description`, diff --git a/forms-flow-web/src/apiManager/services/FOI/foiRequestServices.js b/forms-flow-web/src/apiManager/services/FOI/foiRequestServices.js index 9ca09eb2c..8806a89f0 100644 --- a/forms-flow-web/src/apiManager/services/FOI/foiRequestServices.js +++ b/forms-flow-web/src/apiManager/services/FOI/foiRequestServices.js @@ -528,13 +528,13 @@ export const fetchRestrictedRequestCommentTagList = (requestid, ministryId, ...r export const deleteOIPCDetails = (requestId, ministryId, ...rest) => { const done = fnDone(rest); let apiUrl= replaceUrl(replaceUrl( - API.FOI_REQUEST_API, + API.FOI_REQUEST_SECTION_API, "", ministryId),"",requestId ); const data = {isoipcreview: false, oipcdetails: []} return (dispatch) => { - httpPOSTRequest(`${apiUrl}/deleteoipc`, data) + httpPOSTRequest(`${apiUrl}/oipc`, data) .then((res) => { if (res.data) { done(null, res.data); diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index 90fe23919..0f559f581 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -976,9 +976,6 @@ const FOIRequest = React.memo(({ userDetail }) => { requestDetails?.requestType === FOI_COMPONENT_CONSTANTS.REQUEST_TYPE_GENERAL) } - console.log(requestDetails) - - return (!isLoading && requestDetails && Object.keys(requestDetails).length !== 0) || diff --git a/request-management-api/request_api/resources/foirequest.py b/request-management-api/request_api/resources/foirequest.py index 23fb4d0d8..5d8c5eae5 100644 --- a/request-management-api/request_api/resources/foirequest.py +++ b/request-management-api/request_api/resources/foirequest.py @@ -126,7 +126,6 @@ def post(): @cors_preflight('GET,POST,PUT,OPTIONS') @API.route('/foirequests//ministryrequest/') -@API.route('/foirequests//ministryrequest//') class FOIRequestsById(Resource): """Creates a new version of foi request for iao updates""" @@ -134,17 +133,11 @@ class FOIRequestsById(Resource): @TRACER.trace() @cross_origin(origins=allowedorigins()) @auth.require - def post(foirequestid,foiministryrequestid,actiontype=None): + def post(foirequestid,foiministryrequestid): """ POST Method for capturing FOI requests before processing""" try: - if actiontype == "deleteoipc": - current_foirequest = requestservice().getrequest(foirequestid, foiministryrequestid) - current_foirequest['isoipcreview'] = False - current_foirequest['oipcdetails'] = [] - foirequestschema = FOIRequestWrapperSchema().load(current_foirequest) - else: - request_json = request.get_json() - foirequestschema = FOIRequestWrapperSchema().load(request_json) + request_json = request.get_json() + foirequestschema = FOIRequestWrapperSchema().load(request_json) result = requestservice().saverequestversion(foirequestschema, foirequestid, foiministryrequestid,AuthHelper.getuserid()) if result.success == True: asyncio.ensure_future(eventservice().postevent(foiministryrequestid,"ministryrequest",AuthHelper.getuserid(),AuthHelper.getusername(),AuthHelper.isministrymember())) @@ -299,31 +292,33 @@ def get(ministryrequestid,usertype=None): except BusinessException as exception: return {'status': exception.status_code, 'message':exception.message}, 500 -# @cors_preflight('POST, DELETE, OPTIONS') -# @API.route('/foirequests//ministryrequest//deleteoipc') -# class FOIRequestsById(Resource): -# """Creates a new version of foi request for iao users deleting all oipc details""" -# @staticmethod -# @TRACER.trace() -# @cross_origin(origins=allowedorigins()) -# @auth.require -# def post(foirequestid,foiministryrequestid): -# try: -# current_foirequest = requestservice().getrequest(foirequestid, foiministryrequestid) -# current_foirequest['isoipcreview'] = False -# current_foirequest['oipcdetails'] = [] -# foirequestschema = FOIRequestWrapperSchema().load(current_foirequest) -# result = requestservice().saverequestversion(foirequestschema, foirequestid, foiministryrequestid,AuthHelper.getuserid()) -# if result.success == True: -# asyncio.ensure_future(eventservice().postevent(foiministryrequestid,"ministryrequest",AuthHelper.getuserid(),AuthHelper.getusername(),AuthHelper.isministrymember())) -# metadata = json.dumps({"id": result.identifier, "ministries": result.args[0]}) -# requestservice().posteventtoworkflow(foiministryrequestid, foirequestschema, json.loads(metadata),"iao") -# return {'status': result.success, 'message':result.message,'id':result.identifier, 'ministryRequests': result.args[0]} , 200 -# else: -# return {'status': False, 'message':EXCEPTION_MESSAGE_NOTFOUND_REQUEST,'id':foirequestid} , 404 -# except ValidationError as err: -# return {'status': False, 'message': str(err)}, 400 -# except KeyError as error: -# return {'status': False, 'message': CUSTOM_KEYERROR_MESSAGE + str(error)}, 400 -# except BusinessException as exception: -# return {'status': exception.status_code, 'message':exception.message}, 500 \ No newline at end of file +@cors_preflight('POST, DELETE, UPDATE, OPTIONS') +@API.route('/foirequests//ministryrequest//section/') +class FOIRequestsById(Resource): + """Creates a new version of foi request for iao users adjusting speciifc sections of a FOI Request""" + @staticmethod + @TRACER.trace() + @cross_origin(origins=allowedorigins()) + @auth.require + def post(foirequestid,foiministryrequestid,section): + try: + request_json = request.get_json() + if (section == "oipc"): + foirequest = requestservice().getrequest(foirequestid, foiministryrequestid) + foirequest['isoipcreview'] = request_json['isoipcreview'] + foirequest['oipcdetails'] = request_json['oipcdetails'] + foirequestschema = FOIRequestWrapperSchema().load(foirequest) + result = requestservice().saverequestversion(foirequestschema, foirequestid, foiministryrequestid,AuthHelper.getuserid()) + if result.success == True: + asyncio.ensure_future(eventservice().postevent(foiministryrequestid,"ministryrequest",AuthHelper.getuserid(),AuthHelper.getusername(),AuthHelper.isministrymember())) + metadata = json.dumps({"id": result.identifier, "ministries": result.args[0]}) + requestservice().posteventtoworkflow(foiministryrequestid, foirequestschema, json.loads(metadata),"iao") + return {'status': result.success, 'message':result.message,'id':result.identifier, 'ministryRequests': result.args[0]} , 200 + else: + return {'status': False, 'message':EXCEPTION_MESSAGE_NOTFOUND_REQUEST,'id':foirequestid} , 404 + except ValidationError as err: + return {'status': False, 'message': str(err)}, 400 + except KeyError as error: + return {'status': False, 'message': CUSTOM_KEYERROR_MESSAGE + str(error)}, 400 + except BusinessException as exception: + return {'status': exception.status_code, 'message':exception.message}, 500 \ No newline at end of file From ec681836aa2b30d376360d3a4fc08f218de4bc49 Mon Sep 17 00:00:00 2001 From: Richard Qi Date: Fri, 15 Dec 2023 13:03:09 -0800 Subject: [PATCH 135/238] aggregate search result --- .../models/FOIRequestApplicants.py | 82 +++++++++++++++---- .../request_api/resources/foiapplicant.py | 23 +++--- .../request_api/services/applicantservice.py | 38 +++++---- 3 files changed, 99 insertions(+), 44 deletions(-) diff --git a/request-management-api/request_api/models/FOIRequestApplicants.py b/request-management-api/request_api/models/FOIRequestApplicants.py index 409debee6..b9abcf876 100644 --- a/request-management-api/request_api/models/FOIRequestApplicants.py +++ b/request-management-api/request_api/models/FOIRequestApplicants.py @@ -9,7 +9,7 @@ from .FOIRequests import FOIRequest from .FOIRequestContactInformation import FOIRequestContactInformation from .FOIRequestPersonalAttributes import FOIRequestPersonalAttribute -from sqlalchemy import and_, or_, asc, func +from sqlalchemy import and_, or_, func, case class FOIRequestApplicant(db.Model): # Name of the table in our database @@ -122,8 +122,7 @@ def getapplicantbyemail(cls, email): personalhealthnumber.attributevalue.label('phn') ] - applicantprofile_schema = ApplicantProfileSchema(many=True) - query = _session.query( + subquery_all = _session.query( *selectedcolumns ).join( FOIRequestApplicantMapping, @@ -231,9 +230,35 @@ def getapplicantbyemail(cls, email): FOIMinistryRequest.requeststatusid != 3, FOIRequest.isactive == True, contactemail.contactinformation == email - ).order_by(FOIRequest.foirequestid.asc()) + ).order_by(FOIRequest.foirequestid.desc()).subquery() + + query_aggregate = _session.query( + subquery_all.c.foirequestapplicantid, + func.array_agg(subquery_all.c.firstname).label('firstname'), + func.array_agg(subquery_all.c.middlename).label('middlename'), + func.array_agg(subquery_all.c.lastname).label('lastname'), + func.array_agg(subquery_all.c.alsoknownas).label('alsoknownas'), + func.array_agg(subquery_all.c.dob).label('dob'), + func.array_agg(subquery_all.c.businessname).label('businessname'), + subquery_all.c.applicantversion, + func.array_agg(subquery_all.c.foirequestid).label('foirequestid'), + func.array_agg(subquery_all.c.foirequestversion).label('foirequestversion'), + func.array_agg(subquery_all.c.requesttype).label('requesttype'), + func.array_agg(subquery_all.c.applicantcategory).label('applicantcategory'), + func.array_agg(subquery_all.c.email).label('email'), + func.array_agg(subquery_all.c.address).label('address'), + func.array_agg(subquery_all.c.homephone).label('homephone'), + func.array_agg(subquery_all.c.workphone).label('workphone'), + func.array_agg(subquery_all.c.workphone2).label('workphone2'), + func.array_agg(subquery_all.c.mobilephone).label('mobilephone'), + func.array_agg(subquery_all.c.othercontactinfo).label('othercontactinfo'), + func.array_agg(subquery_all.c.employeenumber).label('employeenumber'), + func.array_agg(subquery_all.c.correctionnumber).label('correctionnumber'), + func.array_agg(subquery_all.c.phn).label('phn') + ).group_by(subquery_all.c.foirequestapplicantid, subquery_all.c.applicantversion) - return applicantprofile_schema.dump(query.all()) + applicantprofile_schema = ApplicantProfileSchema(many=True) + return applicantprofile_schema.dump(query_aggregate.all()) # Search applicant by keywords @@ -291,8 +316,7 @@ def searchapplicant(cls, keywords): personalhealthnumber.attributevalue.label('phn') ] - applicantprofile_schema = ApplicantProfileSchema(many=True) - query = _session.query( + subquery_all = _session.query( *selectedcolumns ).join( FOIRequestApplicantMapping, @@ -401,34 +425,60 @@ def searchapplicant(cls, keywords): FOIMinistryRequest.requeststatusid != 3, FOIRequest.isactive == True, or_(*FOIRequestApplicant.getsearchfilters(keywords, contactemail, contacthomephone, contactworkphone, contactworkphone2, contactmobilephone)) - ).order_by(FOIRequest.foirequestid.asc()) + ).order_by(FOIRequest.foirequestid.desc()).subquery() + + query_aggregate = _session.query( + subquery_all.c.foirequestapplicantid, + func.array_agg(subquery_all.c.firstname).label('firstname'), + func.array_agg(subquery_all.c.middlename).label('middlename'), + func.array_agg(subquery_all.c.lastname).label('lastname'), + func.array_agg(subquery_all.c.alsoknownas).label('alsoknownas'), + func.array_agg(subquery_all.c.dob).label('dob'), + func.array_agg(subquery_all.c.businessname).label('businessname'), + subquery_all.c.applicantversion, + func.array_agg(subquery_all.c.foirequestid).label('foirequestid'), + func.array_agg(subquery_all.c.foirequestversion).label('foirequestversion'), + func.array_agg(subquery_all.c.requesttype).label('requesttype'), + func.array_agg(subquery_all.c.applicantcategory).label('applicantcategory'), + func.array_agg(subquery_all.c.email).label('email'), + func.array_agg(subquery_all.c.address).label('address'), + func.array_agg(subquery_all.c.homephone).label('homephone'), + func.array_agg(subquery_all.c.workphone).label('workphone'), + func.array_agg(subquery_all.c.workphone2).label('workphone2'), + func.array_agg(subquery_all.c.mobilephone).label('mobilephone'), + func.array_agg(subquery_all.c.othercontactinfo).label('othercontactinfo'), + func.array_agg(subquery_all.c.employeenumber).label('employeenumber'), + func.array_agg(subquery_all.c.correctionnumber).label('correctionnumber'), + func.array_agg(subquery_all.c.phn).label('phn') + ).group_by(subquery_all.c.foirequestapplicantid, subquery_all.c.applicantversion) - return applicantprofile_schema.dump(query.all()) + applicantprofile_schema = ApplicantProfileSchema(many=True) + return applicantprofile_schema.dump(query_aggregate.all()) @classmethod def getsearchfilters(cls, keywords, contactemail, contacthomephone, contactworkphone, contactworkphone2, contactmobilephone): searchfilters = [] if(len(keywords) > 0): - if(keywords['firstname'] is not None): + if('firstname' in keywords): searchfilters.append(FOIRequestApplicant.firstname.ilike('%'+keywords['firstname']+'%')) - if(keywords['lastname'] is not None): + if('lastname' in keywords): searchfilters.append(FOIRequestApplicant.lastname.ilike('%'+keywords['lastname']+'%')) - if(keywords['email'] is not None): + if('email' in keywords): searchfilters.append(contactemail.contactinformation.ilike('%'+keywords['email']+'%')) - if(keywords['homephone'] is not None): + if('homephone' in keywords): searchfilters.append(contacthomephone.contactinformation.ilike('%'+keywords['homephone']+'%')) - if(keywords['workphone'] is not None): + if('workphone' in keywords): searchfilters.append(contactworkphone.contactinformation.ilike('%'+keywords['workphone']+'%')) - if(keywords['workphone2'] is not None): + if('workphone2' in keywords): searchfilters.append(contactworkphone2.contactinformation.ilike('%'+keywords['workphone2']+'%')) - if(keywords['mobilephone'] is not None): + if('mobilephone' in keywords): searchfilters.append(contactmobilephone.contactinformation.ilike('%'+keywords['mobilephone']+'%')) return searchfilters diff --git a/request-management-api/request_api/resources/foiapplicant.py b/request-management-api/request_api/resources/foiapplicant.py index 682db49a1..1bc0cfa11 100644 --- a/request-management-api/request_api/resources/foiapplicant.py +++ b/request-management-api/request_api/resources/foiapplicant.py @@ -55,7 +55,6 @@ def get(email=None): return {'status': False, 'message':EXCEPTION_MESSAGE_BAD_REQUEST}, 400 try: result = applicantservice().getapplicantbyemail(email) - print("result-endpoint: ", result) if result is not None: return json.dumps(result), 200 else: @@ -64,7 +63,7 @@ def get(email=None): return {'status': exception.status_code, 'message':exception.message}, 500 -@cors_preflight('GET,OPTIONS') +@cors_preflight('POST,OPTIONS') @API.route('/foiapplicants/search') class EventPagination(Resource): """ Retrives the foi request based on the queue type. @@ -74,20 +73,20 @@ class EventPagination(Resource): @cross_origin(origins=allowedorigins()) @auth.require @auth.isiao - @cors_preflight('GET,OPTIONS') - def get(): + @cors_preflight('POST,OPTIONS') + def post(): try: - _keywords = flask.request.args.get('keywords', None, type=str) - print(_keywords) + requestjson = request.get_json() + _keywords = requestjson['keywords'] - result = [] - statuscode = 200 if _keywords is None or _keywords == "": - result = applicantservice().searchapplicant(_keywords) + return {'status': False, 'message':EXCEPTION_MESSAGE_BAD_REQUEST}, 400 else: - statuscode = 401 - - return result, statuscode + result = applicantservice().searchapplicant(_keywords) + if result is not None: + return json.dumps(result), 200 + else: + return {'status': False, 'message':EXCEPTION_MESSAGE_NOT_FOUND}, 404 except BusinessException as exception: return {'status': exception.status_code, 'message':exception.message}, 500 diff --git a/request-management-api/request_api/services/applicantservice.py b/request-management-api/request_api/services/applicantservice.py index 55cd1730a..fd2d7ebe7 100644 --- a/request-management-api/request_api/services/applicantservice.py +++ b/request-management-api/request_api/services/applicantservice.py @@ -38,33 +38,39 @@ def __validateandtransform(self, filterfields): def __transformfilteringfields(self, filterfields): return list(map(lambda x: x.replace('createdat', 'createdatformatted'), filterfields)) + def __first_not_null(self, list): + for item in list: + if item is not None: + return item + return None + def __prepareapplicant(self, applicant): return { 'additionalPersonalInfo': { - 'alsoKnownAs': applicant["alsoknownas"], - 'birthDate': applicant["dob"], - 'personalHealthNumber': applicant["phn"], + 'alsoKnownAs': self.__first_not_null(applicant["alsoknownas"]), + 'birthDate': self.__first_not_null(applicant["dob"]), + 'personalHealthNumber': self.__first_not_null(applicant["phn"]), }, 'foiRequestApplicantID': applicant["foirequestapplicantid"], - 'firstName': applicant["firstname"], - 'middleName': applicant["middlename"], - 'lastName': applicant["lastname"], + 'firstName': self.__first_not_null(applicant["firstname"]), + 'middleName': self.__first_not_null(applicant["middlename"]), + 'lastName': self.__first_not_null(applicant["lastname"]), #'createdat' : self.__formatedate(applicant["createdat)"], - 'businessName': applicant["businessname"], + 'businessName': self.__first_not_null(applicant["businessname"]), # 'applicant': applicant["applicant"], 'applicantVersion': applicant["applicantversion"], 'foirequestID': applicant["foirequestid"], 'foirequestVersion': applicant["foirequestversion"], 'requestType': applicant["requesttype"], 'category': applicant["applicantcategory"], - 'email':applicant["email"], - 'address': applicant["address"], - 'phonePrimary': applicant["homephone"], - 'workPhonePrimary': applicant["workphone"], - 'workPhoneSecondary': applicant["workphone2"], - 'phoneSecondary': applicant["mobilephone"], - 'otherContactInfo':applicant["othercontactinfo"], - 'publicServiceEmployeeNumber': applicant["employeenumber"], - 'correctionalServiceNumber': applicant["correctionnumber"], + 'email': self.__first_not_null(applicant["email"]), + 'address': self.__first_not_null(applicant["address"]), + 'phonePrimary': self.__first_not_null(applicant["homephone"]), + 'workPhonePrimary': self.__first_not_null(applicant["workphone"]), + 'workPhoneSecondary': self.__first_not_null(applicant["workphone2"]), + 'phoneSecondary': self.__first_not_null(applicant["mobilephone"]), + 'otherContactInfo': self.__first_not_null(applicant["othercontactinfo"]), + 'publicServiceEmployeeNumber': self.__first_not_null(applicant["employeenumber"]), + 'correctionalServiceNumber': self.__first_not_null(applicant["correctionnumber"]), } \ No newline at end of file From b3312967006de90650ff89841ed5b7915e444b21 Mon Sep 17 00:00:00 2001 From: Richard Qi Date: Fri, 15 Dec 2023 16:04:36 -0800 Subject: [PATCH 136/238] bug fix --- .../request_api/models/FOIRequestApplicants.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/request-management-api/request_api/models/FOIRequestApplicants.py b/request-management-api/request_api/models/FOIRequestApplicants.py index b9abcf876..ca51f2bf1 100644 --- a/request-management-api/request_api/models/FOIRequestApplicants.py +++ b/request-management-api/request_api/models/FOIRequestApplicants.py @@ -103,7 +103,7 @@ def getapplicantbyemail(cls, email): FOIRequestApplicant.middlename.label('middlename'), FOIRequestApplicant.lastname.label('lastname'), FOIRequestApplicant.alsoknownas.label('alsoknownas'), - FOIRequestApplicant.dob.label('dob'), + func.to_char(FOIRequestApplicant.dob, 'YYYY-MM-DD').label('dob'), FOIRequestApplicant.businessname.label('businessname'), FOIRequestApplicant.version.label('applicantversion'), FOIRequest.foirequestid.label('foirequestid'), @@ -227,7 +227,7 @@ def getapplicantbyemail(cls, email): personalhealthnumber.attributevalue is not None), isouter=True ).filter( - FOIMinistryRequest.requeststatusid != 3, + # FOIMinistryRequest.requeststatusid != 3, FOIRequest.isactive == True, contactemail.contactinformation == email ).order_by(FOIRequest.foirequestid.desc()).subquery() @@ -297,7 +297,7 @@ def searchapplicant(cls, keywords): FOIRequestApplicant.middlename.label('middlename'), FOIRequestApplicant.lastname.label('lastname'), FOIRequestApplicant.alsoknownas.label('alsoknownas'), - FOIRequestApplicant.dob.label('dob'), + func.to_char(FOIRequestApplicant.dob, 'YYYY-MM-DD').label('dob'), FOIRequestApplicant.businessname.label('businessname'), FOIRequestApplicant.version.label('applicantversion'), FOIRequest.foirequestid.label('foirequestid'), @@ -422,7 +422,7 @@ def searchapplicant(cls, keywords): personalhealthnumber.attributevalue is not None), isouter=True ).filter( - FOIMinistryRequest.requeststatusid != 3, + # FOIMinistryRequest.requeststatusid != 3, FOIRequest.isactive == True, or_(*FOIRequestApplicant.getsearchfilters(keywords, contactemail, contacthomephone, contactworkphone, contactworkphone2, contactmobilephone)) ).order_by(FOIRequest.foirequestid.desc()).subquery() From 156cf1aeb9e28f64e508f1f930d81f6ca8128fab Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Mon, 18 Dec 2023 12:04:32 -0800 Subject: [PATCH 137/238] Work started on ticket 4695. Enums adjusted for download package selections --- .../src/components/FOI/customComponents/Records/index.js | 6 ++++++ forms-flow-web/src/constants/FOI/enum.js | 2 ++ 2 files changed, 8 insertions(+) diff --git a/forms-flow-web/src/components/FOI/customComponents/Records/index.js b/forms-flow-web/src/components/FOI/customComponents/Records/index.js index 764b4ec1f..41b109d47 100644 --- a/forms-flow-web/src/components/FOI/customComponents/Records/index.js +++ b/forms-flow-web/src/components/FOI/customComponents/Records/index.js @@ -832,6 +832,12 @@ export const RecordsLog = ({ } else if (e.target.value === 3 && isResponsePackageDownloadReady) { const s3filepath = responsePackagePdfStitchedRecord?.finalpackagepath; handleDownloadZipFile(s3filepath, e.target.value); + } else if (e.target.value === 4 && isResponsePackageDownloadReady) { + const s3filepath = responsePackagePdfStitchedRecord?.finalpackagepath; + handleDownloadZipFile(s3filepath, e.target.value); + } else if (e.target.value === 5 && isResponsePackageDownloadReady) { + const s3filepath = responsePackagePdfStitchedRecord?.finalpackagepath; + handleDownloadZipFile(s3filepath, e.target.value); } setCurrentDownload(e.target.value); diff --git a/forms-flow-web/src/constants/FOI/enum.js b/forms-flow-web/src/constants/FOI/enum.js index ce2622e6e..24020abc3 100644 --- a/forms-flow-web/src/constants/FOI/enum.js +++ b/forms-flow-web/src/constants/FOI/enum.js @@ -170,6 +170,8 @@ const RecordsDownloadList = [ { id: 1, label: "Download for Harms", disabled: true }, { id: 2, label: "Download Redline for Sign Off", disabled: true }, { id: 3, label: "Download Final Package", disabled: true }, + { id: 4, label: "Download Redline for OIPC Sign Off", disabled: true }, + { id: 5, label: "Download Redline for OIPC Review", disabled: true }, ]; const RecordDownloadCategory = Object.freeze({ From 5d96bacda59e3986317bf87f2b8b4eb1aef68aff Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Mon, 18 Dec 2023 12:43:32 -0800 Subject: [PATCH 138/238] FE for menu items added. WIP download logic + validation logic --- .../components/FOI/customComponents/Records/index.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/forms-flow-web/src/components/FOI/customComponents/Records/index.js b/forms-flow-web/src/components/FOI/customComponents/Records/index.js index 41b109d47..c684d51b6 100644 --- a/forms-flow-web/src/components/FOI/customComponents/Records/index.js +++ b/forms-flow-web/src/components/FOI/customComponents/Records/index.js @@ -375,6 +375,14 @@ export const RecordsLog = ({ useState(false); const [isResponsePackageDownloadFailed, setIsResponsePackageDownloadFailed] = useState(false); + const [isOIPCReviewPackageReady, setIsOIPCReviewPackageReady] = + useState(false); + const [isOIPCReviewPackageFailed, setIsOIPCReviewPackageFailed] = + useState(false); + const [isOIPCSignOffPackageReady, setIsOIPCSignOffPackageReady] = + useState(false); + const [isOIPCSignOffPackageFailed, setIsOIPCSignOffPackageFailed] = + useState(false); const [isAllSelected, setIsAllSelected] = useState(false); useEffect(() => { @@ -832,10 +840,10 @@ export const RecordsLog = ({ } else if (e.target.value === 3 && isResponsePackageDownloadReady) { const s3filepath = responsePackagePdfStitchedRecord?.finalpackagepath; handleDownloadZipFile(s3filepath, e.target.value); - } else if (e.target.value === 4 && isResponsePackageDownloadReady) { + } else if (e.target.value === 4 && isOIPCSignOffPackageReady) { const s3filepath = responsePackagePdfStitchedRecord?.finalpackagepath; handleDownloadZipFile(s3filepath, e.target.value); - } else if (e.target.value === 5 && isResponsePackageDownloadReady) { + } else if (e.target.value === 5 && isOIPCReviewPackageReady) { const s3filepath = responsePackagePdfStitchedRecord?.finalpackagepath; handleDownloadZipFile(s3filepath, e.target.value); } From 5c262a1920426812495f21c8f0280b8bd5227aa1 Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Mon, 18 Dec 2023 15:16:38 -0800 Subject: [PATCH 139/238] Include closed OIPC requests in group filter --- .../request_api/models/FOIMinistryRequests.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index 0c43b1538..8f127614a 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -717,7 +717,9 @@ def getgroupfilters(cls, groups): or_(*groupfilter) ) - return ministryfilter + ministryfilterwithclosedoipc = or_(ministryfilter, and_(FOIMinistryRequest.isoipcreview == True, FOIMinistryRequest.requeststatusid == 3)) + + return ministryfilterwithclosedoipc @classmethod def getrequestoriginalduedate(cls,ministryrequestid): From 26c9ccf2769c349b904ba416b584c76b97e7f3a9 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 19 Dec 2023 10:09:45 -0800 Subject: [PATCH 140/238] intermediate commit for backend code saving changes to all open requests for an applicant --- .../src/apiManager/endpoints/index.js | 2 + .../services/FOI/foiRequestServices.js | 75 +++++++++---------- .../FOI/FOIRequest/ApplicantProfileModal.js | 17 ++--- .../components/FOI/FOIRequest/foirequest.scss | 4 + .../request_api/models/FOIMinistryRequests.py | 9 +++ .../models/FOIRequestApplicants.py | 59 ++++++++++++++- .../request_api/resources/foiapplicant.py | 23 ++++++ .../request_api/schemas/foirequestwrapper.py | 2 +- .../request_api/services/applicantservice.py | 17 ++++- .../foirequest/requestservicecreate.py | 4 +- 10 files changed, 158 insertions(+), 54 deletions(-) diff --git a/forms-flow-web/src/apiManager/endpoints/index.js b/forms-flow-web/src/apiManager/endpoints/index.js index 111ee62ec..3f31e4366 100644 --- a/forms-flow-web/src/apiManager/endpoints/index.js +++ b/forms-flow-web/src/apiManager/endpoints/index.js @@ -38,6 +38,8 @@ const API = { FOI_GET_MINISTRY_REQUEST_WATCHERS: `${FOI_BASE_API_URL}/api/foiwatcher/ministryrequest/`, FOI_GET_CLOSING_REASONS: `${FOI_BASE_API_URL}/api/foiflow/closereasons`, FOI_POST_OSS_HEADER: `${FOI_BASE_API_URL}/api/foiflow/oss/authheader`, + + FOI_GET_REQUEST_APPLICANTS: `${FOI_BASE_API_URL}/api/foiapplicants/`, FOI_GET_PROGRAMAREADIVISIONS: `${FOI_BASE_API_URL}/api/foiadmin/divisions`, FOI_POST_PROGRAMAREADIVISION: `${FOI_BASE_API_URL}/api/foiadmin/division`, diff --git a/forms-flow-web/src/apiManager/services/FOI/foiRequestServices.js b/forms-flow-web/src/apiManager/services/FOI/foiRequestServices.js index 6ad3fcb6f..f6462492a 100644 --- a/forms-flow-web/src/apiManager/services/FOI/foiRequestServices.js +++ b/forms-flow-web/src/apiManager/services/FOI/foiRequestServices.js @@ -527,48 +527,43 @@ export const fetchRestrictedRequestCommentTagList = (requestid, ministryId, ...r } }; -export const fetchPotentialApplicants = async (firstname, lastname, email, phone, ...rest) => { - console.log("fetch applicants" + firstname) - console.log(firstname) - console.log(lastname) +export const fetchPotentialApplicants = (firstname, lastname, email, phone, ...rest) => { + // console.log("fetch applicants" + firstname) + // console.log(firstname) + // console.log(lastname) const done = fnDone(rest); - await new Promise(resolve => {setTimeout(resolve, 3000)}); - done(null, [ - { id: 1, lastName: 'Snow', firstName: 'Jon', age: 35 }, - { id: 2, lastName: 'Lannister', firstName: 'Cersei', age: 42 }, - { id: 3, lastName: 'Lannister', firstName: 'Jaime', age: 45 }, - { id: 4, lastName: 'Stark', firstName: 'Arya', age: 16 }, - { id: 5, lastName: 'Targaryen', firstName: 'Daenerys', age: null }, - { id: 7, lastName: 'Clifford', firstName: 'Ferrara', age: 44 }, - { id: 8, lastName: 'Frances', firstName: 'Rossini', age: 36 }, - { id: 9, lastName: 'Roxie', firstName: 'Harvey', age: 65 }, - ]); - return; - // const apiUrlgetRequestDetails = replaceUrl(replaceUrl( - // API.FOI_MINISTRYVIEW_REQUEST_API, - // "", - // requestId - // ), "", ministryId); - // return (dispatch) => { - // httpGETRequest(apiUrlgetRequestDetails, {}, UserService.getToken()) - // .then((res) => { - // if (res.data) { - // const foiRequest = res.data; - // dispatch(clearMinistryViewRequestDetails({})); - // dispatch(setFOIMinistryViewRequestDetail(foiRequest)); - // dispatch(fetchFOIMinistryAssignedToList(foiRequest.selectedMinistries[0].code.toLowerCase())); - // dispatch(setFOILoader(false)); - // } else { - // dispatch(serviceActionError(res)); - // dispatch(setFOILoader(false)); - // throw new Error(`Error in fetching ministry request details for request# ${requestId} ministry# ${ministryId}`) - // } - // }) - // .catch((error) => { - // catchError(error, dispatch); - // }); - // }; + // await new Promise(resolve => {setTimeout(resolve, 3000)}); + // done(null, [ + // { id: 1, lastName: 'Snow', firstName: 'Jon', age: 35 }, + // { id: 2, lastName: 'Lannister', firstName: 'Cersei', age: 42 }, + // { id: 3, lastName: 'Lannister', firstName: 'Jaime', age: 45 }, + // { id: 4, lastName: 'Stark', firstName: 'Arya', age: 16 }, + // { id: 5, lastName: 'Targaryen', firstName: 'Daenerys', age: null }, + // { id: 7, lastName: 'Clifford', firstName: 'Ferrara', age: 44 }, + // { id: 8, lastName: 'Frances', firstName: 'Rossini', age: 36 }, + // { id: 9, lastName: 'Roxie', firstName: 'Harvey', age: 65 }, + // ]); + // return; + const apiUrlgetRequestDetails = replaceUrl( + API.FOI_GET_REQUEST_APPLICANTS, + "", + email + ); + return (dispatch) => { + httpGETRequest(apiUrlgetRequestDetails, {}, UserService.getToken()) + .then((res) => { + if (res.data) { + done(null, res.data) + } else { + dispatch(serviceActionError(res)); + throw new Error(`Error in fetching potential applicants`) + } + }) + .catch((error) => { + catchError(error, dispatch); + }); + }; }; export const fetchApplicantInfo = async (firstname, ...rest) => { diff --git a/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js b/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js index 5c9264a70..ed01bfb19 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js @@ -86,6 +86,7 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { field: 'birthDate', headerName: 'DATE OF BIRTH', flex: 1, + valueGetter: (params) => params.row?.additionalPersonalInfo?.birthDate }, { field: 'email', @@ -127,7 +128,7 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { if (modalOpen) { setIsLoading(true); if (requestDetails.currentState === StateEnum.intakeinprogress.name) { - fetchPotentialApplicants( + dispatch(fetchPotentialApplicants( requestDetails.firstName, requestDetails.lastName, requestDetails.email, @@ -135,7 +136,7 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { (err, res) => { setRows(res); setIsLoading(false); - }) + })) } else { fetchApplicantInfo(requestDetails.firstName, (err, res) => { setSelectedApplicant(res); @@ -171,9 +172,7 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { } const selectApplicantRow = (e) => { - fetchApplicantInfo(e.firstName, (err, res) => { - setSelectedApplicant(res); - }) + setSelectedApplicant(e.row); } const handleClose = () => { @@ -213,7 +212,6 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { const selectProfile = () => { if (_.isEqual(selectedApplicant, saveApplicantObject) || confirmationMessage) { if (requestDetails.currentState === StateEnum.intakeinprogress.name) { - saveApplicantObject.applicantprofileid = 1; // fill in with actual id later dispatch(setFOIRequestApplicantProfile(saveApplicantObject)); } // call save info api @@ -228,7 +226,7 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { for (let field in selectedApplicant) { if (field === 'additionalPersonalInfo') { for (let infofield in requestDetails[field]) { - if (requestDetails[field][infofield] !== selectedApplicant[field][infofield]) { + if (requestDetails[field][infofield] && requestDetails[field][infofield] !== selectedApplicant[field][infofield]) { updatedApplicant[field][infofield] = requestDetails[field][infofield]; } } @@ -315,7 +313,7 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { [classes.disabledTitle]: !showRequestHistory })} > - Request History ({selectedApplicant.requestHistory.length}) + Request History ({selectedApplicant.foirequestID.length}) : @@ -489,7 +487,7 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { { headerHeight={50} loading={isLoading} onRowClick={selectApplicantRow} + getRowId={(row) => row.foiRequestApplicantID} /> diff --git a/forms-flow-web/src/components/FOI/FOIRequest/foirequest.scss b/forms-flow-web/src/components/FOI/FOIRequest/foirequest.scss index d05c931b4..6b2a8f1f4 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/foirequest.scss +++ b/forms-flow-web/src/components/FOI/FOIRequest/foirequest.scss @@ -202,4 +202,8 @@ height: fit-content; .btn-update-profile { border: none; background: none; +} + +.foi-applicant-data-grid .MuiDataGrid-cellContent{ + text-transform: none !important; } \ No newline at end of file diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index cd6e2a8e9..89b896383 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -221,6 +221,15 @@ def getrequestById(cls,ministryrequestid): request_schema = FOIMinistryRequestSchema(many=True) query = db.session.query(FOIMinistryRequest).filter_by(foiministryrequestid=ministryrequestid).order_by(FOIMinistryRequest.version.asc()) return request_schema.dump(query) + + @classmethod + def getopenrequestsbyrequestId(cls,requestids): + selectedcolumns = [FOIMinistryRequest.foirequest_id, FOIMinistryRequest.foiministryrequestid] + query = db.session.query(selectedcolumns).distinct(FOIMinistryRequest.foiministryrequestid).filter_by(and_( + FOIMinistryRequest.foirequest_id.in_(requestids), + FOIMinistryRequest.requeststatusid != 3 + )).order_by(FOIMinistryRequest.version.asc()) + return [r._asdict() for r in query] @classmethod def getrequeststatusById(cls,ministryrequestid): diff --git a/request-management-api/request_api/models/FOIRequestApplicants.py b/request-management-api/request_api/models/FOIRequestApplicants.py index ca51f2bf1..2c847ac74 100644 --- a/request-management-api/request_api/models/FOIRequestApplicants.py +++ b/request-management-api/request_api/models/FOIRequestApplicants.py @@ -78,11 +78,17 @@ def getapplicantbyemail(cls, email): #aliase for getting contact info contactemail = aliased(FOIRequestContactInformation) contactaddress = aliased(FOIRequestContactInformation) + contactaddress2 = aliased(FOIRequestContactInformation) contacthomephone = aliased(FOIRequestContactInformation) contactworkphone = aliased(FOIRequestContactInformation) contactworkphone2 = aliased(FOIRequestContactInformation) contactmobilephone = aliased(FOIRequestContactInformation) contactother = aliased(FOIRequestContactInformation) + + city = aliased(FOIRequestContactInformation) + province = aliased(FOIRequestContactInformation) + postal = aliased(FOIRequestContactInformation) + country = aliased(FOIRequestContactInformation) #aliase for getting personal attributes personalemployeenumber = aliased(FOIRequestPersonalAttribute) @@ -112,11 +118,16 @@ def getapplicantbyemail(cls, email): ApplicantCategory.name.label('applicantcategory'), contactemail.contactinformation.label('email'), contactaddress.contactinformation.label('address'), + contactaddress2.contactinformation.label('address2'), contacthomephone.contactinformation.label('homephone'), contactworkphone.contactinformation.label('workphone'), contactworkphone2.contactinformation.label('workphone2'), contactmobilephone.contactinformation.label('mobilephone'), contactother.contactinformation.label('othercontactinfo'), + city.contactinformation.label('city'), + province.contactinformation.label('province'), + postal.contactinformation.label('postal'), + country.contactinformation.label('country'), personalemployeenumber.attributevalue.label('employeenumber'), personalcorrectionnumber.attributevalue.label('correctionnumber'), personalhealthnumber.attributevalue.label('phn') @@ -160,7 +171,17 @@ def getapplicantbyemail(cls, email): contactaddress.foirequest_id == FOIRequest.foirequestid, contactaddress.foirequestversion_id == FOIRequest.version, contactaddress.contacttypeid == 2, - contactaddress.contactinformation is not None), + contactaddress.contactinformation is not None, + contactaddress.dataformat == 'address'), + isouter=True + ).join( + contactaddress2, + and_( + contactaddress2.foirequest_id == FOIRequest.foirequestid, + contactaddress2.foirequestversion_id == FOIRequest.version, + contactaddress2.contacttypeid == 2, + contactaddress2.contactinformation is not None, + contactaddress2.dataformat == 'addressSecondary'), isouter=True ).join( contacthomephone, @@ -202,6 +223,42 @@ def getapplicantbyemail(cls, email): contactother.contacttypeid == 7, contactother.contactinformation is not None), isouter=True + ).join( + city, + and_( + city.foirequest_id == FOIRequest.foirequestid, + city.foirequestversion_id == FOIRequest.version, + city.contacttypeid == 2, + city.contactinformation is not None, + city.format == 'city'), + isouter=True + ).join( + province, + and_( + province.foirequest_id == FOIRequest.foirequestid, + province.foirequestversion_id == FOIRequest.version, + province.contacttypeid == 2, + province.contactinformation is not None, + city.format == 'province'), + isouter=True + ).join( + country, + and_( + country.foirequest_id == FOIRequest.foirequestid, + country.foirequestversion_id == FOIRequest.version, + country.contacttypeid == 2, + country.contactinformation is not None, + city.format == 'country'), + isouter=True + ).join( + postal, + and_( + postal.foirequest_id == FOIRequest.foirequestid, + postal.foirequestversion_id == FOIRequest.version, + postal.contacttypeid == 2, + postal.contactinformation is not None, + city.format == 'postal'), + isouter=True ).join( personalemployeenumber, and_( diff --git a/request-management-api/request_api/resources/foiapplicant.py b/request-management-api/request_api/resources/foiapplicant.py index 1bc0cfa11..c191c6d9d 100644 --- a/request-management-api/request_api/resources/foiapplicant.py +++ b/request-management-api/request_api/resources/foiapplicant.py @@ -27,6 +27,7 @@ from flask_cors import cross_origin import request_api from request_api.utils.cache import cache_filter, response_filter +from request_api.schemas.foiapplicant import FOIRequestApplicantSchema API = Namespace('FOIAssignee', description='Endpoints for FOI assignee management') TRACER = Tracer.get_instance() @@ -90,3 +91,25 @@ def post(): except BusinessException as exception: return {'status': exception.status_code, 'message':exception.message}, 500 +@cors_preflight('POST,OPTIONS') +@API.route('/foiapplicants/save') +class EventPagination(Resource): + """ Saves applicant info and request specific contact info for all open requests associated to an applicant + """ + @staticmethod + @TRACER.trace() + @cross_origin(origins=allowedorigins()) + @auth.require + @auth.isiao + @cors_preflight('POST,OPTIONS') + def post(): + try: + applicant = FOIRequestApplicantSchema.load(request.get_json()) + result = applicantservice().saveapplicantinfo(applicant) + if result is not None: + return json.dumps(result), 200 + else: + return {'status': False, 'message':EXCEPTION_MESSAGE_NOT_FOUND}, 404 + except BusinessException as exception: + return {'status': exception.status_code, 'message':exception.message}, 500 + diff --git a/request-management-api/request_api/schemas/foirequestwrapper.py b/request-management-api/request_api/schemas/foirequestwrapper.py index 5e829c84c..f099230f0 100644 --- a/request-management-api/request_api/schemas/foirequestwrapper.py +++ b/request-management-api/request_api/schemas/foirequestwrapper.py @@ -111,7 +111,7 @@ class Meta: # pylint: disable=too-few-public-methods publicServiceEmployeeNumber = fields.Str(data_key="publicServiceEmployeeNumber",allow_none=True, validate=[validate.Length(max=50, error=MAX_EXCEPTION_MESSAGE)]) isiaorestricted = fields.Bool(data_key="isiaorestricted") - applicantprofileid = fields.Int(data_key="applicantprofileid",required=False,allow_none=True) + foiRequestApplicantID = fields.Int(data_key="foiRequestApplicantID",required=False,allow_none=True) selectedMinistries = fields.Nested(FOIMinistryRequestWrapperSchema, many=True) additionalPersonalInfo = fields.Nested(FOIAdditionallPersonalInfoWrapperSchema,required=False,allow_none=True) diff --git a/request-management-api/request_api/services/applicantservice.py b/request-management-api/request_api/services/applicantservice.py index fd2d7ebe7..551fb10ff 100644 --- a/request-management-api/request_api/services/applicantservice.py +++ b/request-management-api/request_api/services/applicantservice.py @@ -2,11 +2,14 @@ from os import stat from re import VERBOSE from request_api.models.FOIRequestApplicants import FOIRequestApplicant +from request_api.models.FOIMinistryRequests import FOIMinistryRequest +from request_api.services.requestservice import requestservicegetter, requestservicecreate from request_api.auth import AuthHelper from dateutil import tz, parser from flask import jsonify from datetime import datetime as datetime2 from request_api.utils.commons.datetimehandler import datetimehandler +from request_api.models.default_method_result import DefaultMethodResult import re class applicantservice: @@ -31,6 +34,18 @@ def searchapplicant(self, keywords): applicantqueue.append(self.__prepareapplicant(applicant)) return applicantqueue + + def saveapplicantinfo(self, applicantschema): + requests = FOIMinistryRequest.getopenrequestsbyrequestId(applicantschema['foirequestID']) + for request in requests: + requestschema = requestservicegetter().getrequest(request['foirequest_id'], request['foiministryrequestid']) + requestschema.update(applicantschema) + responseschema = requestservicecreate().saverequestversion( + requestschema, request['foirequest_id'], request['foiministryrequestid'], AuthHelper.getuserid() + ) + if not responseschema.success: + return responseschema + return DefaultMethodResult(True,'Applicant Info Updated',applicantschema['foiRequestApplicantID']) def __validateandtransform(self, filterfields): return self.__transformfilteringfields(filterfields) @@ -62,7 +77,7 @@ def __prepareapplicant(self, applicant): 'foirequestID': applicant["foirequestid"], 'foirequestVersion': applicant["foirequestversion"], 'requestType': applicant["requesttype"], - 'category': applicant["applicantcategory"], + # 'category': applicant["applicantcategory"], 'email': self.__first_not_null(applicant["email"]), 'address': self.__first_not_null(applicant["address"]), 'phonePrimary': self.__first_not_null(applicant["homephone"]), diff --git a/request-management-api/request_api/services/foirequest/requestservicecreate.py b/request-management-api/request_api/services/foirequest/requestservicecreate.py index 555c8570e..e33828807 100644 --- a/request-management-api/request_api/services/foirequest/requestservicecreate.py +++ b/request-management-api/request_api/services/foirequest/requestservicecreate.py @@ -128,9 +128,9 @@ def __prepareapplicants(self, foirequestschema, userid): selfalsoknownas=None selfdob=None if foirequestschema.get("additionalPersonalInfo") is not None and foirequestschema.get('requeststatusid') == 1: - if foirequestschema.get('applicantprofileid', None): + if foirequestschema.get('foiRequestApplicantID', None): requestapplicant = FOIRequestApplicantMapping() - requestapplicant.foirequestapplicantid = foirequestschema['applicantprofileid'] + requestapplicant.foirequestapplicantid = foirequestschema['foiRequestApplicantID'] requestapplicant.requestortypeid = RequestorType().getrequestortype("Self")["requestortypeid"] requestapplicantarr.append(requestapplicant) else: From dd4ee25776e6295efd00f5a7a87482a6abe7c1d6 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 19 Dec 2023 10:47:42 -0800 Subject: [PATCH 141/238] add missing applicant schema file --- .../request_api/schemas/foiapplicant.py | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 request-management-api/request_api/schemas/foiapplicant.py diff --git a/request-management-api/request_api/schemas/foiapplicant.py b/request-management-api/request_api/schemas/foiapplicant.py new file mode 100644 index 000000000..517d9bb93 --- /dev/null +++ b/request-management-api/request_api/schemas/foiapplicant.py @@ -0,0 +1,39 @@ +from marshmallow import EXCLUDE, Schema, fields, validate +from request_api.utils.constants import MAX_EXCEPTION_MESSAGE, BLANK_EXCEPTION_MESSAGE +from request_api.schemas.foirequestwrapper import FOIAdditionallPersonalInfoWrapperSchema + +class FOIRequestApplicantSchema(Schema): + + class Meta: # pylint: disable=too-few-public-methods + """Exclude unknown fields in the deserialized output.""" + + unknown = EXCLUDE + firstName = fields.Str(data_key="firstName", required=True,validate=[validate.Length(min=1, error=BLANK_EXCEPTION_MESSAGE, max=50)]) + middleName = fields.Str(data_key="middleName",allow_none=True, validate=[validate.Length(max=50, error=MAX_EXCEPTION_MESSAGE)]) + lastName = fields.Str(data_key="lastName", required=True,validate=[validate.Length(min=1, error=BLANK_EXCEPTION_MESSAGE, max=50)]) + email = fields.Str(data_key="email",allow_none=True, validate=[validate.Length(max=120, error=MAX_EXCEPTION_MESSAGE)]) + businessName = fields.Str(data_key="businessName",allow_none=True, validate=[validate.Length(max=255, error=MAX_EXCEPTION_MESSAGE)]) + + phonePrimary = fields.Str(data_key="phonePrimary",allow_none=True, validate=[validate.Length(max=50, error=MAX_EXCEPTION_MESSAGE)]) + workPhonePrimary = fields.Str(data_key="workPhonePrimary",allow_none=True, validate=[validate.Length(max=50, error=MAX_EXCEPTION_MESSAGE)]) + phoneSecondary = fields.Str(data_key="phoneSecondary",allow_none=True, validate=[validate.Length(max=50, error=MAX_EXCEPTION_MESSAGE)]) + workPhoneSecondary = fields.Str(data_key="workPhoneSecondary",allow_none=True, validate=[validate.Length(max=50, error=MAX_EXCEPTION_MESSAGE)]) + address = fields.Str(data_key="address",allow_none=True, validate=[validate.Length(max=120, error=MAX_EXCEPTION_MESSAGE)]) + addressSecondary = fields.Str(data_key="addressSecondary",allow_none=True, validate=[validate.Length(max=120, error=MAX_EXCEPTION_MESSAGE)]) + city = fields.Str(data_key="city",allow_none=True, validate=[validate.Length(max=120, error=MAX_EXCEPTION_MESSAGE)]) + province = fields.Str(data_key="province",allow_none=True, validate=[validate.Length(max=120, error=MAX_EXCEPTION_MESSAGE)]) + postal = fields.Str(data_key="postal",allow_none=True, validate=[validate.Length(max=10, error=MAX_EXCEPTION_MESSAGE)]) + country = fields.Str(data_key="country",allow_none=True) + # correctionalServiceNumber = fields.Str(data_key="correctionalServiceNumber",allow_none=True, validate=[validate.Length(max=50, error=MAX_EXCEPTION_MESSAGE)]) + # publicServiceEmployeeNumber = fields.Str(data_key="publicServiceEmployeeNumber",allow_none=True, validate=[validate.Length(max=50, error=MAX_EXCEPTION_MESSAGE)]) + + + foiRequestApplicantID = fields.Int(data_key="foiRequestApplicantID",required=False,allow_none=True) + + foirequestID = fields.List(fields.Int(),data_key="foirequestID",required=True,allow_none=False) + + + additionalPersonalInfo = fields.Nested(FOIAdditionallPersonalInfoWrapperSchema,required=False,allow_none=True) + + + \ No newline at end of file From 16865d2767be24e6cd2a8dea6fb6e987ef291662 Mon Sep 17 00:00:00 2001 From: divyav-aot Date: Tue, 19 Dec 2023 14:27:38 -0500 Subject: [PATCH 142/238] small fix for search applicant --- .../request_api/models/FOIRequestApplicants.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/request-management-api/request_api/models/FOIRequestApplicants.py b/request-management-api/request_api/models/FOIRequestApplicants.py index 2c847ac74..8ac66cdf1 100644 --- a/request-management-api/request_api/models/FOIRequestApplicants.py +++ b/request-management-api/request_api/models/FOIRequestApplicants.py @@ -35,6 +35,7 @@ class FOIRequestApplicant(db.Model): @classmethod def saveapplicant(cls,firstname, lastname, middlename, businessname, alsoknownas, dob, userid): dbquery = db.session.query(FOIRequestApplicant) + # check the applicantid instead of firstname and lastname dbquery = dbquery.filter_by(firstname=firstname) applicant = dbquery.filter_by(lastname=lastname) if (applicant.count() > 0): @@ -230,7 +231,7 @@ def getapplicantbyemail(cls, email): city.foirequestversion_id == FOIRequest.version, city.contacttypeid == 2, city.contactinformation is not None, - city.format == 'city'), + city.dataformat == 'city'), isouter=True ).join( province, @@ -239,7 +240,7 @@ def getapplicantbyemail(cls, email): province.foirequestversion_id == FOIRequest.version, province.contacttypeid == 2, province.contactinformation is not None, - city.format == 'province'), + city.dataformat == 'province'), isouter=True ).join( country, @@ -248,7 +249,7 @@ def getapplicantbyemail(cls, email): country.foirequestversion_id == FOIRequest.version, country.contacttypeid == 2, country.contactinformation is not None, - city.format == 'country'), + city.dataformat == 'country'), isouter=True ).join( postal, @@ -257,7 +258,7 @@ def getapplicantbyemail(cls, email): postal.foirequestversion_id == FOIRequest.version, postal.contacttypeid == 2, postal.contactinformation is not None, - city.format == 'postal'), + city.dataformat == 'postal'), isouter=True ).join( personalemployeenumber, From e4097bcb05aad443ea7624526e0c87c43436c644 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Tue, 19 Dec 2023 17:04:02 -0800 Subject: [PATCH 143/238] Testing for OIPCREview package download WIP + logic for oipc redline WIP --- .../src/actions/FOI/foiActionConstants.js | 4 +- .../src/actions/FOI/foiRequestActions.js | 12 +++ .../src/apiManager/endpoints/index.js | 5 + .../services/FOI/foiRecordServices.js | 79 ++++++++++++++++ .../FOI/customComponents/Records/index.js | 92 +++++++++++++++---- .../src/modules/FOI/foiRequestsReducer.js | 11 +++ 6 files changed, 182 insertions(+), 21 deletions(-) diff --git a/forms-flow-web/src/actions/FOI/foiActionConstants.js b/forms-flow-web/src/actions/FOI/foiActionConstants.js index 8a94f7f00..4bce8f078 100644 --- a/forms-flow-web/src/actions/FOI/foiActionConstants.js +++ b/forms-flow-web/src/actions/FOI/foiActionConstants.js @@ -89,7 +89,9 @@ const FOI_ACTION_CONSTANTS = { "FOI_PDF_STITCHED_STATUS_FOR_RESPONSEPACKAGE", FOI_PDF_STITCHED_RECORD_FOR_RESPONSEPACKAGE: "FOI_PDF_STITCHED_RECORD_FOR_RESPONSEPACKAGE", - + FOI_PDF_STITCHED_STATUS_FOR_OIPCREVIEWPACKAGE: "FOI_PDF_STITCHED_STATUS_FOR_OIPCREVIEWPACKAGE", + FOI_PDF_STITCHED_RECORD_FOR_OIPCREVIEWPACKAGE: "FOI_PDF_STITCHED_RECORD_FOR_OIPCREVIEWPACKAGE", + OIPC_OUTCOMES: "OIPC_OUTCOMES", OIPC_STATUSES: "OIPC_STATUSES", OIPC_REVIEWTYPES: "OIPC_REVIEWTYPES", diff --git a/forms-flow-web/src/actions/FOI/foiRequestActions.js b/forms-flow-web/src/actions/FOI/foiRequestActions.js index ad9a7beb7..688e8c508 100644 --- a/forms-flow-web/src/actions/FOI/foiRequestActions.js +++ b/forms-flow-web/src/actions/FOI/foiRequestActions.js @@ -147,6 +147,12 @@ export const setFOIPDFStitchedRecordForResponsePackage = payload: data, }); }; +export const setFOIPDFStitchedRecordForOipcReviewPackage = (data) => (dispatch) => { + dispatch({ + type: FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_RECORD_FOR_OIPCREVIEWPACKAGE, + payload: data, + }); +} export const setFOIPDFStitchStatusForHarms = (data) => (dispatch) => { dispatch({ type: FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_STATUS_FOR_HARMS, @@ -166,6 +172,12 @@ export const setFOIPDFStitchStatusForResponsePackage = (data) => (dispatch) => { payload: data, }); }; +export const setFOIPDFStitchStatusForOipcReviewPackage = (data) => (dispatch) => { + dispatch({ + type: FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_STATUS_FOR_OIPCREVIEWPACKAGE, + payload: data, + }); +}; export const serviceActionError = (_data) => (dispatch) => { //TODO update to a common file diff --git a/forms-flow-web/src/apiManager/endpoints/index.js b/forms-flow-web/src/apiManager/endpoints/index.js index fd9939a87..6c8502570 100644 --- a/forms-flow-web/src/apiManager/endpoints/index.js +++ b/forms-flow-web/src/apiManager/endpoints/index.js @@ -135,6 +135,11 @@ const API = { FOI_DOWNLOAD_RECORDS_FOR_RESPONSEPACKAGE: `${FOI_BASE_API_URL}/api/foirecord//ministryrequest//download/responsepackage`, FOI_PDF_STITCH_STATUS_FOR_RESPONSEPACKAGE: `${FOI_BASE_API_URL}/api/foirecord//ministryrequest//responsepackage/pdfstitchjobstatus`, + FOI_DOWNLOAD_RECORDS_FOR_OIPCREVIEWPACKAGE: `${FOI_BASE_API_URL}/api/foirecord//ministryrequest//download/oipcreview`, + FOI_PDF_STITCH_STATUS_FOR_OIPCREVIEWPACKAGE: `${FOI_BASE_API_URL}/api/foirecord//ministryrequest//oipcreview/pdfstitchjobstatus`, + FOI_DOWNLOAD_RECORDS_FOR_OIPCREDLINE: `${FOI_BASE_API_URL}/api/foirecord//ministryrequest//download/oipcredline`, + FOI_PDF_STITCH_STATUS_FOR_OIPCREDLINE: `${FOI_BASE_API_URL}/api/foirecord//ministryrequest//oipcredline/pdfstitchjobstatus`, + FOI_GET_OIPC_OUTCOMES: `${FOI_BASE_API_URL}/api/foiflow/oipc/outcomes`, FOI_GET_OIPC_STATUSES: `${FOI_BASE_API_URL}/api/foiflow/oipc/statuses`, FOI_GET_OIPC_REVIEWTYPES: `${FOI_BASE_API_URL}/api/foiflow/oipc/reviewtypes`, diff --git a/forms-flow-web/src/apiManager/services/FOI/foiRecordServices.js b/forms-flow-web/src/apiManager/services/FOI/foiRecordServices.js index b729be708..94dc70202 100644 --- a/forms-flow-web/src/apiManager/services/FOI/foiRecordServices.js +++ b/forms-flow-web/src/apiManager/services/FOI/foiRecordServices.js @@ -17,6 +17,8 @@ import { setFOIPDFStitchedRecordForRedlines, setFOIPDFStitchStatusForResponsePackage, setFOIPDFStitchedRecordForResponsePackage, + setFOIPDFStitchedRecordForOipcReviewPackage, + setFOIPDFStitchStatusForOipcReviewPackage, } from "../../../actions/FOI/foiRequestActions"; import { fnDone } from "./foiServicesUtil"; import UserService from "../../../services/UserService"; @@ -479,3 +481,80 @@ export const fetchPDFStitchedRecordForResponsePackage = ( }); }; }; + +export const fetchPDFStitchedStatusForOIPCRedline = () => { + return; +} + +export const fetchPDFStitchedRecordForOIPCRedline = () => { + return; +} + +export const fetchPDFStitchedStatusForOIPCReviewPackage = ( + requestId, + ministryId, + ...rest) => { + if (!ministryId) { + return () => {}; + } + const done = fnDone(rest); + let apiUrl = replaceUrl( + replaceUrl( + API.FOI_PDF_STITCH_STATUS_FOR_OIPCREVIEWPACKAGE, + "", + ministryId + ), + "", + requestId + ); + return (dispatch) => { + httpGETRequest(apiUrl, {}, UserService.getToken()) + .then((res) => { + if (res.data) { + dispatch(setFOIPDFStitchStatusForOipcReviewPackage(res.data)); + done(null, res.data); + } + }) + .catch((error) => { + console.log("Error in fetching pdfstitch job status", error); + dispatch(serviceActionError(error)); + done(error); + }); + }; + } + +export const fetchPDFStitchedRecordForOIPCReviewPackage = ( + requestId, + ministryId, + ...rest) => { + if (!ministryId) { + return () => {}; + } + const done = fnDone(rest); + let apiUrl = replaceUrl( + replaceUrl( + API.FOI_DOWNLOAD_RECORDS_FOR_OIPCREVIEWPACKAGE, + "", + ministryId + ), + "", + requestId + ); + return (dispatch) => { + httpGETRequest(apiUrl, {}, UserService.getToken()) + .then((res) => { + if (res.data) { + dispatch(setFOIPDFStitchedRecordForOipcReviewPackage(res.data)); + done(null, res.data); + } else { + console.log("Error in fetching records for redlines", res); + dispatch(serviceActionError(res)); + } + }) + .catch((error) => { + console.log("Error in fetching records for redlines", error); + dispatch(serviceActionError(error)); + done(error); + }); + }; + } \ No newline at end of file diff --git a/forms-flow-web/src/components/FOI/customComponents/Records/index.js b/forms-flow-web/src/components/FOI/customComponents/Records/index.js index c684d51b6..88447a55d 100644 --- a/forms-flow-web/src/components/FOI/customComponents/Records/index.js +++ b/forms-flow-web/src/components/FOI/customComponents/Records/index.js @@ -30,6 +30,8 @@ import { fetchPDFStitchedRecordForHarms, fetchPDFStitchedRecordForRedlines, fetchPDFStitchedRecordForResponsePackage, + fetchPDFStitchedRecordForOIPCRedline, + fetchPDFStitchedRecordForOIPCReviewPackage, checkForRecordsChange, } from "../../../../apiManager/services/FOI/foiRecordServices"; import { @@ -62,14 +64,6 @@ import TextField from "@mui/material/TextField"; import { saveAs } from "file-saver"; import { downloadZip } from "client-zip"; import { ClickableChip } from "../../Dashboard/utils"; -import CircularProgress from "@mui/material/CircularProgress"; -import AttachmentFilter from "../Attachments/AttachmentFilter"; -import Accordion from "@material-ui/core/Accordion"; -import Stack from "@mui/material/Stack"; -import AccordionSummary from "@material-ui/core/AccordionSummary"; -import AccordionDetails from "@material-ui/core/AccordionDetails"; -import Typography from "@material-ui/core/Typography"; -import ExpandMoreIcon from "@material-ui/icons/ExpandMore"; import SearchIcon from "@material-ui/icons/Search"; import InputAdornment from "@mui/material/InputAdornment"; import InputBase from "@mui/material/InputBase"; @@ -80,15 +74,12 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faCheckCircle, faClone, - faTrashAlt, - faTrashCan, } from "@fortawesome/free-regular-svg-icons"; import { faSpinner, faExclamationCircle, faBan, faArrowTurnUp, - faHistory, faTrash, faPenToSquare, faLinkSlash, @@ -237,6 +228,12 @@ export const RecordsLog = ({ let redlinePdfStitchStatus = useSelector( (state) => state.foiRequests.foiPDFStitchStatusForRedlines ); + let oipcReviewPackagePdfStitchedStatus = useSelector( + (state) => state.foiRequests.foiPDFStitchStatusForOipcReviewPackage + ); + let oipcRedlinePdfStitchedStatus = useSelector( + (state) => state.foiRequests.foiPDFStitchStatusForOipcRedline + ); let responsePackagePdfStitchStatus = useSelector( (state) => state.foiRequests.foiPDFStitchStatusForResponsePackage ); @@ -247,6 +244,12 @@ export const RecordsLog = ({ let redlinePdfStitchedRecord = useSelector( (state) => state.foiRequests.foiPDFStitchedRecordForRedlines ); + let oipcReviewPackagePdfStitchedRecord = useSelector( + (state) => state.foiRequests.foiPDFStitchedRecordForOipcReviewPackage + ); + let oipcRedlinePdfStitchedRecord = useSelector( + (state) => state.foiRequests.foiPDFStitchedRecordForOipcRedline + ); let responsePackagePdfStitchedRecord = useSelector( (state) => state.foiRequests.foiPDFStitchedRecordForResponsePackage ); @@ -379,9 +382,13 @@ export const RecordsLog = ({ useState(false); const [isOIPCReviewPackageFailed, setIsOIPCReviewPackageFailed] = useState(false); - const [isOIPCSignOffPackageReady, setIsOIPCSignOffPackageReady] = + const [isOIPCReviewPackageInProgress, setIsOIPCReviewPackageInProgress] = + useState(false); + const [isOIPCRedlineReady, setIsOIPCRedlineReady] = useState(false); - const [isOIPCSignOffPackageFailed, setIsOIPCSignOffPackageFailed] = + const [isOIPCRedlineFailed, setIsOIPCRedlineFailed] = + useState(false); + const [isOIPCRedlineInProgress, setIsOIPCRedlineInProgress] = useState(false); const [isAllSelected, setIsAllSelected] = useState(false); @@ -446,10 +453,29 @@ export const RecordsLog = ({ setIsResponsePackageDownloadFailed, fetchPDFStitchedRecordForResponsePackage ); + + // Update OIPC Review Package PDF Stitch Status + updateStatus( + oipcReviewPackagePdfStitchedStatus, + setIsOIPCReviewPackageInProgress, + setIsOIPCReviewPackageReady, + setIsOIPCReviewPackageFailed, + fetchPDFStitchedRecordForOIPCReviewPackage + ); + // Update Redline OIPC PDF Stitch Status + updateStatus( + oipcRedlinePdfStitchedStatus, + setIsOIPCRedlineInProgress, + setIsOIPCRedlineReady, + setIsOIPCRedlineFailed, + fetchPDFStitchedRecordForOIPCRedline + ); }, [ pdfStitchStatus, redlinePdfStitchStatus, responsePackagePdfStitchStatus, + oipcRedlinePdfStitchedStatus, + oipcReviewPackagePdfStitchedStatus, requestId, ministryId, ]); @@ -462,8 +488,14 @@ export const RecordsLog = ({ if (item.id === 3 && isResponsePackageDownloadReady) { item.disabled = false; } + if (item.id === 4 && isOIPCRedlineReady) { + item.disabled = false; + } + if (item.id === 5 && isOIPCReviewPackageReady) { + item.disabled = false; + } }); - }, [isRedlineDownloadReady, isResponsePackageDownloadReady]); + }, [isRedlineDownloadReady, isResponsePackageDownloadReady, isOIPCRedlineReady, isOIPCReviewPackageReady]); const addAttachments = () => { setModalFor("add"); @@ -840,11 +872,11 @@ export const RecordsLog = ({ } else if (e.target.value === 3 && isResponsePackageDownloadReady) { const s3filepath = responsePackagePdfStitchedRecord?.finalpackagepath; handleDownloadZipFile(s3filepath, e.target.value); - } else if (e.target.value === 4 && isOIPCSignOffPackageReady) { - const s3filepath = responsePackagePdfStitchedRecord?.finalpackagepath; + } else if (e.target.value === 4 && isOIPCRedlineReady) { + const s3filepath = oipcRedlinePdfStitchedRecord?.finalpackagepath; handleDownloadZipFile(s3filepath, e.target.value); } else if (e.target.value === 5 && isOIPCReviewPackageReady) { - const s3filepath = responsePackagePdfStitchedRecord?.finalpackagepath; + const s3filepath = oipcReviewPackagePdfStitchedRecord?.finalpackagepath; handleDownloadZipFile(s3filepath, e.target.value); } @@ -1020,6 +1052,14 @@ export const RecordsLog = ({ setIsResponsePackageDownloadInProgress(false); setIsResponsePackageDownloadReady(false); setIsResponsePackageDownloadFailed(true); + } else if (itemid === 4) { + setIsOIPCRedlineInProgress(false); + setIsOIPCRedlineReady(false); + setIsOIPCRedlineFailed(true); + } else if (itemid === 5) { + setIsOIPCReviewPackageInProgress(false); + setIsOIPCReviewPackageReady(false); + setIsOIPCReviewPackageFailed(true); } }; @@ -1027,7 +1067,9 @@ export const RecordsLog = ({ return ( (itemid === 1 && isDownloadReady) || (itemid === 2 && isRedlineDownloadReady) || - (itemid === 3 && isResponsePackageDownloadReady) + (itemid === 3 && isResponsePackageDownloadReady) || + (itemid === 4 && isOIPCRedlineReady) || + (itemid === 5 && isOIPCReviewPackageReady) ); }; @@ -1035,7 +1077,9 @@ export const RecordsLog = ({ return ( (itemid === 1 && isDownloadFailed) || (itemid === 2 && isRedlineDownloadFailed) || - (itemid === 3 && isResponsePackageDownloadFailed) + (itemid === 3 && isResponsePackageDownloadFailed) || + (itemid === 4 && isOIPCRedlineFailed) || + (itemid === 5 && isOIPCReviewPackageFailed) ); }; @@ -1043,7 +1087,9 @@ export const RecordsLog = ({ return ( (itemid === 1 && isDownloadInProgress) || (itemid === 2 && isRedlineDownloadInProgress) || - (itemid === 3 && isResponsePackageDownloadInProgress) + (itemid === 3 && isResponsePackageDownloadInProgress) || + (itemid === 4 && isOIPCRedlineInProgress) || + (itemid === 5 && isOIPCReviewPackageInProgress) ); }; @@ -1593,6 +1639,12 @@ export const RecordsLog = ({ ); }; + console.log(responsePackagePdfStitchedRecord); + console.log(responsePackagePdfStitchStatus); + console.log("BREAK") + console.log(oipcReviewPackagePdfStitchedRecord); + console.log(oipcReviewPackagePdfStitchedStatus); + return (
{isAttachmentLoading ? ( diff --git a/forms-flow-web/src/modules/FOI/foiRequestsReducer.js b/forms-flow-web/src/modules/FOI/foiRequestsReducer.js index 9edb8ab4e..40d839ac1 100644 --- a/forms-flow-web/src/modules/FOI/foiRequestsReducer.js +++ b/forms-flow-web/src/modules/FOI/foiRequestsReducer.js @@ -57,10 +57,14 @@ const initialState = { }, foiPDFStitchedRecordForHarms: {}, foiPDFStitchedRecordForRedlines: {}, + foiPDFStitchedRecordForOipcReviewPackage: {}, + foiPDFStitchedRecordForOipcRedline: {}, foiPDFStitchedRecordForResponsePackage: {}, foiPDFStitchStatusForHarms: "not started", foiPDFStitchStatusForRedlines: "not started", foiPDFStitchStatusForResponsePackage: "not started", + foiPDFStitchStatusForOipcReviewPackage: "not started", + foiPDFStitchStatusForOipcRedline: "not started", foiRequestCFRForm: { overallsuggestions: "", status: "init", @@ -268,12 +272,19 @@ const foiRequests = (state = initialState, action) => { ...state, foiPDFStitchedRecordForResponsePackage: action.payload, }; + case FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_RECORD_FOR_OIPCREVIEWPACKAGE: + return { + ...state, + foiPDFStitchedRecordForOipcReviewPackage: action.payload, + }; case FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_STATUS_FOR_HARMS: return { ...state, foiPDFStitchStatusForHarms: action.payload }; case FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_STATUS_FOR_REDLINES: return { ...state, foiPDFStitchStatusForRedlines: action.payload }; case FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_STATUS_FOR_RESPONSEPACKAGE: return { ...state, foiPDFStitchStatusForResponsePackage: action.payload }; + case FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_STATUS_FOR_OIPCREVIEWPACKAGE: + return { ...state, foiPDFStitchStatusForOipcReviewPackage: action.payload }; case FOI_ACTION_CONSTANTS.FOI_REQUEST_CFR_FORM: return { ...state, From d4aab09609fb9e5f06b40dbffa79c119de2bd0b0 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 19 Dec 2023 17:43:23 -0800 Subject: [PATCH 144/238] 2nd intermediate commit for save applicant profile fixed front end bug with general requests --- .../src/apiManager/endpoints/index.js | 1 + .../services/FOI/foiRequestServices.js | 22 ++++++++++++++++++- .../FOI/FOIRequest/ApplicantProfileModal.js | 15 ++++++++----- .../request_api/models/FOIMinistryRequests.py | 4 ++-- .../models/FOIRequestApplicants.py | 8 +++---- .../request_api/resources/foiapplicant.py | 10 ++++----- .../request_api/services/applicantservice.py | 13 +++++++++-- 7 files changed, 54 insertions(+), 19 deletions(-) diff --git a/forms-flow-web/src/apiManager/endpoints/index.js b/forms-flow-web/src/apiManager/endpoints/index.js index 3f31e4366..2ed298394 100644 --- a/forms-flow-web/src/apiManager/endpoints/index.js +++ b/forms-flow-web/src/apiManager/endpoints/index.js @@ -40,6 +40,7 @@ const API = { FOI_POST_OSS_HEADER: `${FOI_BASE_API_URL}/api/foiflow/oss/authheader`, FOI_GET_REQUEST_APPLICANTS: `${FOI_BASE_API_URL}/api/foiapplicants/`, + FOI_SAVE_REQUEST_APPLICANT_INFO: `${FOI_BASE_API_URL}/api/foiapplicants/save`, FOI_GET_PROGRAMAREADIVISIONS: `${FOI_BASE_API_URL}/api/foiadmin/divisions`, FOI_POST_PROGRAMAREADIVISION: `${FOI_BASE_API_URL}/api/foiadmin/division`, diff --git a/forms-flow-web/src/apiManager/services/FOI/foiRequestServices.js b/forms-flow-web/src/apiManager/services/FOI/foiRequestServices.js index f6462492a..563acf7e5 100644 --- a/forms-flow-web/src/apiManager/services/FOI/foiRequestServices.js +++ b/forms-flow-web/src/apiManager/services/FOI/foiRequestServices.js @@ -612,4 +612,24 @@ export const fetchApplicantContactHistory = (...rest) => { username: "foiintake@idir", }] ); -} \ No newline at end of file +} + +export const saveApplicantInfo = (applicant, ...rest) => { + const done = fnDone(rest); + const apiUrlgetRequestDetails = API.FOI_SAVE_REQUEST_APPLICANT_INFO; + return (dispatch) => { + httpPOSTRequest(apiUrlgetRequestDetails, applicant, UserService.getToken()) + .then((res) => { + if (res.data) { + dispatch(setRestrictedReqTaglist(res.data)); + done(null, res.data); + } else { + dispatch(serviceActionError(res)); + throw new Error(`Error in saving applicant`); + } + }) + .catch((error) => { + catchError(error, dispatch); + }); + } +}; \ No newline at end of file diff --git a/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js b/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js index ed01bfb19..d5ff602b4 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js @@ -16,7 +16,7 @@ import SearchIcon from "@material-ui/icons/Search"; import InputAdornment from "@mui/material/InputAdornment"; import InputBase from "@mui/material/InputBase"; import Grid from "@mui/material/Grid"; -import { fetchPotentialApplicants, fetchApplicantInfo, fetchApplicantContactHistory } from "../../../apiManager/services/FOI/foiRequestServices"; +import { fetchPotentialApplicants, fetchApplicantInfo, fetchApplicantContactHistory, saveApplicantInfo } from "../../../apiManager/services/FOI/foiRequestServices"; import AddressContactDetails from "./AddressContanctInfo"; import ApplicantDetails from "./ApplicantDetails" import AdditionalApplicantDetails from "./AdditionalApplicantDetails"; @@ -148,7 +148,7 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { useEffect(() => { setSaveApplicantObject({...selectedApplicant}) for (let field in selectedApplicant) { - if (field === 'additionalPersonalInfo') { + if (field === 'additionalPersonalInfo' && requestDetails.requestType === 'personal') { if ((requestDetails[field][FOI_COMPONENT_CONSTANTS.DOB] && selectedApplicant[field][FOI_COMPONENT_CONSTANTS.DOB] !== requestDetails[field][FOI_COMPONENT_CONSTANTS.DOB]) || (requestDetails[field][FOI_COMPONENT_CONSTANTS.PERSONAL_HEALTH_NUMBER] && selectedApplicant[field][FOI_COMPONENT_CONSTANTS.PERSONAL_HEALTH_NUMBER] !== requestDetails[field][FOI_COMPONENT_CONSTANTS.PERSONAL_HEALTH_NUMBER])) { setIsProfileDifferent(true); @@ -214,8 +214,13 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { if (requestDetails.currentState === StateEnum.intakeinprogress.name) { dispatch(setFOIRequestApplicantProfile(saveApplicantObject)); } - // call save info api - handleClose() + // set loading screen + dispatch(saveApplicantInfo(saveApplicantObject, (err, res) => { + if (!err) { + // unset loading screen + handleClose(); + } + })); } else { setConfirmationMessage(true); } @@ -224,7 +229,7 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { const copyInfo = () => { let updatedApplicant = {...selectedApplicant} for (let field in selectedApplicant) { - if (field === 'additionalPersonalInfo') { + if (field === 'additionalPersonalInfo' && requestDetails.requestType === 'personal') { for (let infofield in requestDetails[field]) { if (requestDetails[field][infofield] && requestDetails[field][infofield] !== selectedApplicant[field][infofield]) { updatedApplicant[field][infofield] = requestDetails[field][infofield]; diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index 89b896383..c784dfed6 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -225,10 +225,10 @@ def getrequestById(cls,ministryrequestid): @classmethod def getopenrequestsbyrequestId(cls,requestids): selectedcolumns = [FOIMinistryRequest.foirequest_id, FOIMinistryRequest.foiministryrequestid] - query = db.session.query(selectedcolumns).distinct(FOIMinistryRequest.foiministryrequestid).filter_by(and_( + query = db.session.query(*selectedcolumns).distinct(FOIMinistryRequest.foiministryrequestid).filter( FOIMinistryRequest.foirequest_id.in_(requestids), FOIMinistryRequest.requeststatusid != 3 - )).order_by(FOIMinistryRequest.version.asc()) + ).order_by(FOIMinistryRequest.foiministryrequestid.asc(), FOIMinistryRequest.version.asc()) return [r._asdict() for r in query] @classmethod diff --git a/request-management-api/request_api/models/FOIRequestApplicants.py b/request-management-api/request_api/models/FOIRequestApplicants.py index 2c847ac74..bc36eaa6b 100644 --- a/request-management-api/request_api/models/FOIRequestApplicants.py +++ b/request-management-api/request_api/models/FOIRequestApplicants.py @@ -230,7 +230,7 @@ def getapplicantbyemail(cls, email): city.foirequestversion_id == FOIRequest.version, city.contacttypeid == 2, city.contactinformation is not None, - city.format == 'city'), + city.dataformat == 'city'), isouter=True ).join( province, @@ -239,7 +239,7 @@ def getapplicantbyemail(cls, email): province.foirequestversion_id == FOIRequest.version, province.contacttypeid == 2, province.contactinformation is not None, - city.format == 'province'), + city.dataformat == 'province'), isouter=True ).join( country, @@ -248,7 +248,7 @@ def getapplicantbyemail(cls, email): country.foirequestversion_id == FOIRequest.version, country.contacttypeid == 2, country.contactinformation is not None, - city.format == 'country'), + city.dataformat == 'country'), isouter=True ).join( postal, @@ -257,7 +257,7 @@ def getapplicantbyemail(cls, email): postal.foirequestversion_id == FOIRequest.version, postal.contacttypeid == 2, postal.contactinformation is not None, - city.format == 'postal'), + city.dataformat == 'postal'), isouter=True ).join( personalemployeenumber, diff --git a/request-management-api/request_api/resources/foiapplicant.py b/request-management-api/request_api/resources/foiapplicant.py index c191c6d9d..0ff131d71 100644 --- a/request-management-api/request_api/resources/foiapplicant.py +++ b/request-management-api/request_api/resources/foiapplicant.py @@ -18,7 +18,7 @@ import flask from flask_restx import Namespace, Resource, cors from flask_expects_json import expects_json -from request_api.auth import auth +from request_api.auth import auth, AuthHelper from request_api.tracer import Tracer from request_api.utils.util import cors_preflight, allowedorigins from request_api.exceptions import BusinessException, Error @@ -104,10 +104,10 @@ class EventPagination(Resource): @cors_preflight('POST,OPTIONS') def post(): try: - applicant = FOIRequestApplicantSchema.load(request.get_json()) - result = applicantservice().saveapplicantinfo(applicant) - if result is not None: - return json.dumps(result), 200 + applicant = FOIRequestApplicantSchema().load(request.get_json()) + result = applicantservice().saveapplicantinfo(applicant, AuthHelper.getuserid()) + if result.success: + return {'status': result.success, 'message':result.message,'id':result.identifier} , 200 else: return {'status': False, 'message':EXCEPTION_MESSAGE_NOT_FOUND}, 404 except BusinessException as exception: diff --git a/request-management-api/request_api/services/applicantservice.py b/request-management-api/request_api/services/applicantservice.py index 551fb10ff..799d58bcc 100644 --- a/request-management-api/request_api/services/applicantservice.py +++ b/request-management-api/request_api/services/applicantservice.py @@ -35,13 +35,22 @@ def searchapplicant(self, keywords): return applicantqueue - def saveapplicantinfo(self, applicantschema): + def saveapplicantinfo(self, applicantschema, userid): + FOIRequestApplicant.saveapplicant( + applicantschema['firstName'], + applicantschema['lastName'], + applicantschema['middleName'], + applicantschema['businessName'], + applicantschema.get('additionalPersonalInfo', None).get('alsoKnownAs', None), + applicantschema.get('additionalPersonalInfo', None).get('birthDate', None), + userid + ) # replace with applicant id once new save function is written requests = FOIMinistryRequest.getopenrequestsbyrequestId(applicantschema['foirequestID']) for request in requests: requestschema = requestservicegetter().getrequest(request['foirequest_id'], request['foiministryrequestid']) requestschema.update(applicantschema) responseschema = requestservicecreate().saverequestversion( - requestschema, request['foirequest_id'], request['foiministryrequestid'], AuthHelper.getuserid() + requestschema, request['foirequest_id'], request['foiministryrequestid'], userid ) if not responseschema.success: return responseschema From dd68f54f19688ae0858a70ca6a48ed11696a7942 Mon Sep 17 00:00:00 2001 From: divyav-aot Date: Wed, 20 Dec 2023 11:45:14 -0500 Subject: [PATCH 145/238] comments added --- .../src/components/FOI/FOIRequest/ApplicantProfileModal.js | 1 + .../request_api/models/FOIRequestApplicants.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js b/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js index ed01bfb19..45c241bfb 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js @@ -148,6 +148,7 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { useEffect(() => { setSaveApplicantObject({...selectedApplicant}) for (let field in selectedApplicant) { + // Ignore comparison of additional fields like DOB if it is a general request if (field === 'additionalPersonalInfo') { if ((requestDetails[field][FOI_COMPONENT_CONSTANTS.DOB] && selectedApplicant[field][FOI_COMPONENT_CONSTANTS.DOB] !== requestDetails[field][FOI_COMPONENT_CONSTANTS.DOB]) || (requestDetails[field][FOI_COMPONENT_CONSTANTS.PERSONAL_HEALTH_NUMBER] && selectedApplicant[field][FOI_COMPONENT_CONSTANTS.PERSONAL_HEALTH_NUMBER] !== requestDetails[field][FOI_COMPONENT_CONSTANTS.PERSONAL_HEALTH_NUMBER])) { diff --git a/request-management-api/request_api/models/FOIRequestApplicants.py b/request-management-api/request_api/models/FOIRequestApplicants.py index 8ac66cdf1..088d3ad88 100644 --- a/request-management-api/request_api/models/FOIRequestApplicants.py +++ b/request-management-api/request_api/models/FOIRequestApplicants.py @@ -35,7 +35,7 @@ class FOIRequestApplicant(db.Model): @classmethod def saveapplicant(cls,firstname, lastname, middlename, businessname, alsoknownas, dob, userid): dbquery = db.session.query(FOIRequestApplicant) - # check the applicantid instead of firstname and lastname + ### check the applicantid instead of firstname and lastname dbquery = dbquery.filter_by(firstname=firstname) applicant = dbquery.filter_by(lastname=lastname) if (applicant.count() > 0): From 2c2a03e8fa9f6fedc03db04791532e5057dcefbd Mon Sep 17 00:00:00 2001 From: divyav-aot Date: Wed, 20 Dec 2023 12:30:57 -0500 Subject: [PATCH 146/238] fix related to show applicant details --- .../src/components/FOI/FOIRequest/ApplicantProfileModal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js b/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js index d5ff602b4..b8f09d752 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js @@ -148,7 +148,7 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { useEffect(() => { setSaveApplicantObject({...selectedApplicant}) for (let field in selectedApplicant) { - if (field === 'additionalPersonalInfo' && requestDetails.requestType === 'personal') { + if (field === 'additionalPersonalInfo' && requestDetails[field] && requestDetails.requestType === 'personal') { if ((requestDetails[field][FOI_COMPONENT_CONSTANTS.DOB] && selectedApplicant[field][FOI_COMPONENT_CONSTANTS.DOB] !== requestDetails[field][FOI_COMPONENT_CONSTANTS.DOB]) || (requestDetails[field][FOI_COMPONENT_CONSTANTS.PERSONAL_HEALTH_NUMBER] && selectedApplicant[field][FOI_COMPONENT_CONSTANTS.PERSONAL_HEALTH_NUMBER] !== requestDetails[field][FOI_COMPONENT_CONSTANTS.PERSONAL_HEALTH_NUMBER])) { setIsProfileDifferent(true); From 4d69f5b3509e1ea48b7fc9df51a7a4f458f8a82e Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Wed, 20 Dec 2023 12:54:52 -0800 Subject: [PATCH 147/238] Download FE integration for OIPCRedline and OIPCREview files created. WIP Testing to s3 bucket for dl of actual oipcreview and oipc redline files --- .../src/actions/FOI/foiActionConstants.js | 2 + .../src/actions/FOI/foiRequestActions.js | 12 +++ .../services/FOI/foiRecordServices.js | 75 +++++++++++++++++-- .../components/FOI/FOIRequest/FOIRequest.js | 4 + .../MinistryReview/MinistryReview.js | 6 ++ .../src/modules/FOI/foiRequestsReducer.js | 7 ++ 6 files changed, 100 insertions(+), 6 deletions(-) diff --git a/forms-flow-web/src/actions/FOI/foiActionConstants.js b/forms-flow-web/src/actions/FOI/foiActionConstants.js index 4bce8f078..5d8f40f0a 100644 --- a/forms-flow-web/src/actions/FOI/foiActionConstants.js +++ b/forms-flow-web/src/actions/FOI/foiActionConstants.js @@ -91,6 +91,8 @@ const FOI_ACTION_CONSTANTS = { "FOI_PDF_STITCHED_RECORD_FOR_RESPONSEPACKAGE", FOI_PDF_STITCHED_STATUS_FOR_OIPCREVIEWPACKAGE: "FOI_PDF_STITCHED_STATUS_FOR_OIPCREVIEWPACKAGE", FOI_PDF_STITCHED_RECORD_FOR_OIPCREVIEWPACKAGE: "FOI_PDF_STITCHED_RECORD_FOR_OIPCREVIEWPACKAGE", + FOI_PDF_STITCHED_STATUS_FOR_OIPCREDLINE: "FOI_PDF_STITCHED_STATUS_FOR_OIPCREDLINE", + FOI_PDF_STITCHED_RECORD_FOR_OIPCREDLINE: "FOI_PDF_STITCHED_RECORD_FOR_OIPCREDLINE", OIPC_OUTCOMES: "OIPC_OUTCOMES", OIPC_STATUSES: "OIPC_STATUSES", diff --git a/forms-flow-web/src/actions/FOI/foiRequestActions.js b/forms-flow-web/src/actions/FOI/foiRequestActions.js index 688e8c508..2d75baf4e 100644 --- a/forms-flow-web/src/actions/FOI/foiRequestActions.js +++ b/forms-flow-web/src/actions/FOI/foiRequestActions.js @@ -153,6 +153,12 @@ export const setFOIPDFStitchedRecordForOipcReviewPackage = (data) => (dispatch) payload: data, }); } +export const setFOIPDFStitchedRecordForOipcRedline = (data) => (dispatch) => { + dispatch({ + type: FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_RECORD_FOR_OIPCREDLINE, + payload: data, + }); +} export const setFOIPDFStitchStatusForHarms = (data) => (dispatch) => { dispatch({ type: FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_STATUS_FOR_HARMS, @@ -178,6 +184,12 @@ export const setFOIPDFStitchStatusForOipcReviewPackage = (data) => (dispatch) => payload: data, }); }; +export const setFOIPDFStitchStatusForOipcRedline = (data) => (dispatch) => { + dispatch({ + type: FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_STATUS_FOR_OIPCREDLINE, + payload: data, + }); +}; export const serviceActionError = (_data) => (dispatch) => { //TODO update to a common file diff --git a/forms-flow-web/src/apiManager/services/FOI/foiRecordServices.js b/forms-flow-web/src/apiManager/services/FOI/foiRecordServices.js index 94dc70202..4de7b2a33 100644 --- a/forms-flow-web/src/apiManager/services/FOI/foiRecordServices.js +++ b/forms-flow-web/src/apiManager/services/FOI/foiRecordServices.js @@ -19,6 +19,8 @@ import { setFOIPDFStitchedRecordForResponsePackage, setFOIPDFStitchedRecordForOipcReviewPackage, setFOIPDFStitchStatusForOipcReviewPackage, + setFOIPDFStitchStatusForOipcRedline, + setFOIPDFStitchedRecordForOipcRedline, } from "../../../actions/FOI/foiRequestActions"; import { fnDone } from "./foiServicesUtil"; import UserService from "../../../services/UserService"; @@ -482,13 +484,74 @@ export const fetchPDFStitchedRecordForResponsePackage = ( }; }; -export const fetchPDFStitchedStatusForOIPCRedline = () => { - return; -} +export const fetchPDFStitchedStatusForOIPCRedline = ( + requestId, + ministryId, + ...rest) => { + if (!ministryId) { + return () => {}; + } + const done = fnDone(rest); + let apiUrl = replaceUrl( + replaceUrl( + API.FOI_PDF_STITCH_STATUS_FOR_OIPCREDLINE, + "", + ministryId + ), + "", + requestId + ); + return (dispatch) => { + httpGETRequest(apiUrl, {}, UserService.getToken()) + .then((res) => { + if (res.data) { + dispatch(setFOIPDFStitchStatusForOipcRedline(res.data)); + done(null, res.data); + } + }) + .catch((error) => { + console.log("Error in fetching pdfstitch job status", error); + dispatch(serviceActionError(error)); + done(error); + }); + }; + } -export const fetchPDFStitchedRecordForOIPCRedline = () => { - return; -} +export const fetchPDFStitchedRecordForOIPCRedline = ( + requestId, + ministryId, + ...rest) => { + if (!ministryId) { + return () => {}; + } + const done = fnDone(rest); + let apiUrl = replaceUrl( + replaceUrl( + API.FOI_DOWNLOAD_RECORDS_FOR_OIPCREDLINE, + "", + ministryId + ), + "", + requestId + ); + return (dispatch) => { + httpGETRequest(apiUrl, {}, UserService.getToken()) + .then((res) => { + if (res.data) { + dispatch(setFOIPDFStitchedRecordForOipcRedline(res.data)); + done(null, res.data); + } else { + console.log("Error in fetching records for redlines", res); + dispatch(serviceActionError(res)); + } + }) + .catch((error) => { + console.log("Error in fetching records for redlines", error); + dispatch(serviceActionError(error)); + done(error); + }); + }; + } export const fetchPDFStitchedStatusForOIPCReviewPackage = ( requestId, diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index 0f559f581..690ce671a 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -49,6 +49,8 @@ import { fetchRedactedSections, fetchPDFStitchStatusForRedlines, fetchPDFStitchStatusForResponsePackage, + fetchPDFStitchedStatusForOIPCReviewPackage, + fetchPDFStitchedStatusForOIPCRedline, } from "../../../apiManager/services/FOI/foiRecordServices"; import { makeStyles } from "@material-ui/core/styles"; import FOI_COMPONENT_CONSTANTS from "../../../constants/FOI/foiComponentConstants"; @@ -301,6 +303,8 @@ const FOIRequest = React.memo(({ userDetail }) => { dispatch(fetchPDFStitchStatusForHarms(requestId, ministryId)); dispatch(fetchPDFStitchStatusForRedlines(requestId, ministryId)); dispatch(fetchPDFStitchStatusForResponsePackage(requestId, ministryId)); + dispatch(fetchPDFStitchedStatusForOIPCRedline(requestId, ministryId)); + dispatch(fetchPDFStitchedStatusForOIPCReviewPackage(requestId, ministryId)); fetchCFRForm(ministryId, dispatch); dispatch(fetchApplicantCorrespondence(requestId, ministryId)); dispatch(fetchApplicantCorrespondenceTemplates()); diff --git a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js index d3b9cccdf..6c88b5e46 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js @@ -29,6 +29,8 @@ import { fetchPDFStitchStatusForHarms, fetchPDFStitchStatusForRedlines, fetchPDFStitchStatusForResponsePackage, + fetchPDFStitchedStatusForOIPCReviewPackage, + fetchPDFStitchedStatusForOIPCRedline, } from "../../../../apiManager/services/FOI/foiRecordServices"; import { fetchCFRForm } from "../../../../apiManager/services/FOI/foiCFRFormServices"; @@ -213,6 +215,8 @@ const MinistryReview = React.memo(({ userDetail }) => { dispatch(fetchPDFStitchStatusForHarms(requestId, ministryId)); dispatch(fetchPDFStitchStatusForRedlines(requestId, ministryId)); dispatch(fetchPDFStitchStatusForResponsePackage(requestId, ministryId)); + dispatch(fetchPDFStitchedStatusForOIPCRedline(requestId, ministryId)); + dispatch(fetchPDFStitchedStatusForOIPCReviewPackage(requestId, ministryId)); fetchCFRForm(ministryId, dispatch); if (bcgovcode) dispatch(fetchFOIMinistryAssignedToList(bcgovcode)); } @@ -345,6 +349,8 @@ const MinistryReview = React.memo(({ userDetail }) => { dispatch(fetchPDFStitchStatusForHarms(requestId, ministryId)); dispatch(fetchPDFStitchStatusForRedlines(requestId, ministryId)); dispatch(fetchPDFStitchStatusForResponsePackage(requestId, ministryId)); + dispatch(fetchPDFStitchedStatusForOIPCRedline(requestId, ministryId)); + dispatch(fetchPDFStitchedStatusForOIPCReviewPackage(requestId, ministryId)); fetchCFRForm(ministryId, dispatch); setStateChanged(false); setcurrentrequestStatus(_state); diff --git a/forms-flow-web/src/modules/FOI/foiRequestsReducer.js b/forms-flow-web/src/modules/FOI/foiRequestsReducer.js index 40d839ac1..6108546c8 100644 --- a/forms-flow-web/src/modules/FOI/foiRequestsReducer.js +++ b/forms-flow-web/src/modules/FOI/foiRequestsReducer.js @@ -277,6 +277,11 @@ const foiRequests = (state = initialState, action) => { ...state, foiPDFStitchedRecordForOipcReviewPackage: action.payload, }; + case FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_RECORD_FOR_OIPCREDLINE: + return { + ...state, + foiPDFStitchedRecordForOipcRedline: action.payload, + }; case FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_STATUS_FOR_HARMS: return { ...state, foiPDFStitchStatusForHarms: action.payload }; case FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_STATUS_FOR_REDLINES: @@ -285,6 +290,8 @@ const foiRequests = (state = initialState, action) => { return { ...state, foiPDFStitchStatusForResponsePackage: action.payload }; case FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_STATUS_FOR_OIPCREVIEWPACKAGE: return { ...state, foiPDFStitchStatusForOipcReviewPackage: action.payload }; + case FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_STATUS_FOR_OIPCREDLINE: + return { ...state, foiPDFStitchStatusForOipcRedline: action.payload }; case FOI_ACTION_CONSTANTS.FOI_REQUEST_CFR_FORM: return { ...state, From 4f73bd0f9e73c01b35ae9d0cd2ff11f1b1ca40d7 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Wed, 20 Dec 2023 14:21:57 -0800 Subject: [PATCH 148/238] Adjusted oipcreviewpackage naming convention to oipcredlinereview --- .../src/actions/FOI/foiActionConstants.js | 4 +- .../src/actions/FOI/foiRequestActions.js | 8 +-- .../src/apiManager/endpoints/index.js | 4 +- .../services/FOI/foiRecordServices.js | 16 +++--- .../components/FOI/FOIRequest/FOIRequest.js | 4 +- .../MinistryReview/MinistryReview.js | 6 +-- .../FOI/customComponents/Records/index.js | 54 +++++++++---------- .../src/modules/FOI/foiRequestsReducer.js | 12 ++--- 8 files changed, 51 insertions(+), 57 deletions(-) diff --git a/forms-flow-web/src/actions/FOI/foiActionConstants.js b/forms-flow-web/src/actions/FOI/foiActionConstants.js index 5d8f40f0a..f9acfee86 100644 --- a/forms-flow-web/src/actions/FOI/foiActionConstants.js +++ b/forms-flow-web/src/actions/FOI/foiActionConstants.js @@ -89,8 +89,8 @@ const FOI_ACTION_CONSTANTS = { "FOI_PDF_STITCHED_STATUS_FOR_RESPONSEPACKAGE", FOI_PDF_STITCHED_RECORD_FOR_RESPONSEPACKAGE: "FOI_PDF_STITCHED_RECORD_FOR_RESPONSEPACKAGE", - FOI_PDF_STITCHED_STATUS_FOR_OIPCREVIEWPACKAGE: "FOI_PDF_STITCHED_STATUS_FOR_OIPCREVIEWPACKAGE", - FOI_PDF_STITCHED_RECORD_FOR_OIPCREVIEWPACKAGE: "FOI_PDF_STITCHED_RECORD_FOR_OIPCREVIEWPACKAGE", + FOI_PDF_STITCHED_STATUS_FOR_OIPCREDLINEREVIEW: "FOI_PDF_STITCHED_STATUS_FOR_OIPCREDLINEREVIEW", + FOI_PDF_STITCHED_RECORD_FOR_OIPCREDLINEREVIEW: "FOI_PDF_STITCHED_RECORD_FOR_OIPCREDLINEREVIEW", FOI_PDF_STITCHED_STATUS_FOR_OIPCREDLINE: "FOI_PDF_STITCHED_STATUS_FOR_OIPCREDLINE", FOI_PDF_STITCHED_RECORD_FOR_OIPCREDLINE: "FOI_PDF_STITCHED_RECORD_FOR_OIPCREDLINE", diff --git a/forms-flow-web/src/actions/FOI/foiRequestActions.js b/forms-flow-web/src/actions/FOI/foiRequestActions.js index 2d75baf4e..55d3aca7b 100644 --- a/forms-flow-web/src/actions/FOI/foiRequestActions.js +++ b/forms-flow-web/src/actions/FOI/foiRequestActions.js @@ -147,9 +147,9 @@ export const setFOIPDFStitchedRecordForResponsePackage = payload: data, }); }; -export const setFOIPDFStitchedRecordForOipcReviewPackage = (data) => (dispatch) => { +export const setFOIPDFStitchedRecordForOipcRedlineReview = (data) => (dispatch) => { dispatch({ - type: FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_RECORD_FOR_OIPCREVIEWPACKAGE, + type: FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_RECORD_FOR_OIPCREDLINEREVIEW, payload: data, }); } @@ -178,9 +178,9 @@ export const setFOIPDFStitchStatusForResponsePackage = (data) => (dispatch) => { payload: data, }); }; -export const setFOIPDFStitchStatusForOipcReviewPackage = (data) => (dispatch) => { +export const setFOIPDFStitchStatusForOipcRedlineReview = (data) => (dispatch) => { dispatch({ - type: FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_STATUS_FOR_OIPCREVIEWPACKAGE, + type: FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_STATUS_FOR_OIPCREDLINEREVIEW, payload: data, }); }; diff --git a/forms-flow-web/src/apiManager/endpoints/index.js b/forms-flow-web/src/apiManager/endpoints/index.js index 6c8502570..f8aeb111d 100644 --- a/forms-flow-web/src/apiManager/endpoints/index.js +++ b/forms-flow-web/src/apiManager/endpoints/index.js @@ -135,8 +135,8 @@ const API = { FOI_DOWNLOAD_RECORDS_FOR_RESPONSEPACKAGE: `${FOI_BASE_API_URL}/api/foirecord//ministryrequest//download/responsepackage`, FOI_PDF_STITCH_STATUS_FOR_RESPONSEPACKAGE: `${FOI_BASE_API_URL}/api/foirecord//ministryrequest//responsepackage/pdfstitchjobstatus`, - FOI_DOWNLOAD_RECORDS_FOR_OIPCREVIEWPACKAGE: `${FOI_BASE_API_URL}/api/foirecord//ministryrequest//download/oipcreview`, - FOI_PDF_STITCH_STATUS_FOR_OIPCREVIEWPACKAGE: `${FOI_BASE_API_URL}/api/foirecord//ministryrequest//oipcreview/pdfstitchjobstatus`, + FOI_DOWNLOAD_RECORDS_FOR_OIPCREDLINEREVIEW: `${FOI_BASE_API_URL}/api/foirecord//ministryrequest//download/oipcredlinereview`, + FOI_PDF_STITCH_STATUS_FOR_OIPCREDLINEREVIEW: `${FOI_BASE_API_URL}/api/foirecord//ministryrequest//oipcredlinereview/pdfstitchjobstatus`, FOI_DOWNLOAD_RECORDS_FOR_OIPCREDLINE: `${FOI_BASE_API_URL}/api/foirecord//ministryrequest//download/oipcredline`, FOI_PDF_STITCH_STATUS_FOR_OIPCREDLINE: `${FOI_BASE_API_URL}/api/foirecord//ministryrequest//oipcredline/pdfstitchjobstatus`, diff --git a/forms-flow-web/src/apiManager/services/FOI/foiRecordServices.js b/forms-flow-web/src/apiManager/services/FOI/foiRecordServices.js index 4de7b2a33..8c2d48a61 100644 --- a/forms-flow-web/src/apiManager/services/FOI/foiRecordServices.js +++ b/forms-flow-web/src/apiManager/services/FOI/foiRecordServices.js @@ -17,8 +17,8 @@ import { setFOIPDFStitchedRecordForRedlines, setFOIPDFStitchStatusForResponsePackage, setFOIPDFStitchedRecordForResponsePackage, - setFOIPDFStitchedRecordForOipcReviewPackage, - setFOIPDFStitchStatusForOipcReviewPackage, + setFOIPDFStitchedRecordForOipcRedlineReview, + setFOIPDFStitchStatusForOipcRedlineReview, setFOIPDFStitchStatusForOipcRedline, setFOIPDFStitchedRecordForOipcRedline, } from "../../../actions/FOI/foiRequestActions"; @@ -553,7 +553,7 @@ export const fetchPDFStitchedRecordForOIPCRedline = ( }; } -export const fetchPDFStitchedStatusForOIPCReviewPackage = ( +export const fetchPDFStitchedStatusForOIPCRedlineReview = ( requestId, ministryId, ...rest) => { @@ -563,7 +563,7 @@ export const fetchPDFStitchedStatusForOIPCReviewPackage = ( const done = fnDone(rest); let apiUrl = replaceUrl( replaceUrl( - API.FOI_PDF_STITCH_STATUS_FOR_OIPCREVIEWPACKAGE, + API.FOI_PDF_STITCH_STATUS_FOR_OIPCREDLINEREVIEW, "", ministryId ), @@ -574,7 +574,7 @@ export const fetchPDFStitchedStatusForOIPCReviewPackage = ( httpGETRequest(apiUrl, {}, UserService.getToken()) .then((res) => { if (res.data) { - dispatch(setFOIPDFStitchStatusForOipcReviewPackage(res.data)); + dispatch(setFOIPDFStitchStatusForOipcRedlineReview(res.data)); done(null, res.data); } }) @@ -586,7 +586,7 @@ export const fetchPDFStitchedStatusForOIPCReviewPackage = ( }; } -export const fetchPDFStitchedRecordForOIPCReviewPackage = ( +export const fetchPDFStitchedRecordForOIPCRedlineReview = ( requestId, ministryId, ...rest) => { @@ -596,7 +596,7 @@ export const fetchPDFStitchedRecordForOIPCReviewPackage = ( const done = fnDone(rest); let apiUrl = replaceUrl( replaceUrl( - API.FOI_DOWNLOAD_RECORDS_FOR_OIPCREVIEWPACKAGE, + API.FOI_DOWNLOAD_RECORDS_FOR_OIPCREDLINEREVIEW, "", ministryId ), @@ -607,7 +607,7 @@ export const fetchPDFStitchedRecordForOIPCReviewPackage = ( httpGETRequest(apiUrl, {}, UserService.getToken()) .then((res) => { if (res.data) { - dispatch(setFOIPDFStitchedRecordForOipcReviewPackage(res.data)); + dispatch(setFOIPDFStitchedRecordForOipcRedlineReview(res.data)); done(null, res.data); } else { console.log("Error in fetching records for redlines", res); diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index 690ce671a..5c7d8db01 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -49,7 +49,7 @@ import { fetchRedactedSections, fetchPDFStitchStatusForRedlines, fetchPDFStitchStatusForResponsePackage, - fetchPDFStitchedStatusForOIPCReviewPackage, + fetchPDFStitchedStatusForOIPCRedlineReview, fetchPDFStitchedStatusForOIPCRedline, } from "../../../apiManager/services/FOI/foiRecordServices"; import { makeStyles } from "@material-ui/core/styles"; @@ -304,7 +304,7 @@ const FOIRequest = React.memo(({ userDetail }) => { dispatch(fetchPDFStitchStatusForRedlines(requestId, ministryId)); dispatch(fetchPDFStitchStatusForResponsePackage(requestId, ministryId)); dispatch(fetchPDFStitchedStatusForOIPCRedline(requestId, ministryId)); - dispatch(fetchPDFStitchedStatusForOIPCReviewPackage(requestId, ministryId)); + dispatch(fetchPDFStitchedStatusForOIPCRedlineReview(requestId, ministryId)); fetchCFRForm(ministryId, dispatch); dispatch(fetchApplicantCorrespondence(requestId, ministryId)); dispatch(fetchApplicantCorrespondenceTemplates()); diff --git a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js index 6c88b5e46..0bcde8b35 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js @@ -29,7 +29,7 @@ import { fetchPDFStitchStatusForHarms, fetchPDFStitchStatusForRedlines, fetchPDFStitchStatusForResponsePackage, - fetchPDFStitchedStatusForOIPCReviewPackage, + fetchPDFStitchedStatusForOIPCRedlineReview, fetchPDFStitchedStatusForOIPCRedline, } from "../../../../apiManager/services/FOI/foiRecordServices"; @@ -216,7 +216,7 @@ const MinistryReview = React.memo(({ userDetail }) => { dispatch(fetchPDFStitchStatusForRedlines(requestId, ministryId)); dispatch(fetchPDFStitchStatusForResponsePackage(requestId, ministryId)); dispatch(fetchPDFStitchedStatusForOIPCRedline(requestId, ministryId)); - dispatch(fetchPDFStitchedStatusForOIPCReviewPackage(requestId, ministryId)); + dispatch(fetchPDFStitchedStatusForOIPCRedlineReview(requestId, ministryId)); fetchCFRForm(ministryId, dispatch); if (bcgovcode) dispatch(fetchFOIMinistryAssignedToList(bcgovcode)); } @@ -350,7 +350,7 @@ const MinistryReview = React.memo(({ userDetail }) => { dispatch(fetchPDFStitchStatusForRedlines(requestId, ministryId)); dispatch(fetchPDFStitchStatusForResponsePackage(requestId, ministryId)); dispatch(fetchPDFStitchedStatusForOIPCRedline(requestId, ministryId)); - dispatch(fetchPDFStitchedStatusForOIPCReviewPackage(requestId, ministryId)); + dispatch(fetchPDFStitchedStatusForOIPCRedlineReview(requestId, ministryId)); fetchCFRForm(ministryId, dispatch); setStateChanged(false); setcurrentrequestStatus(_state); diff --git a/forms-flow-web/src/components/FOI/customComponents/Records/index.js b/forms-flow-web/src/components/FOI/customComponents/Records/index.js index 88447a55d..85373fdac 100644 --- a/forms-flow-web/src/components/FOI/customComponents/Records/index.js +++ b/forms-flow-web/src/components/FOI/customComponents/Records/index.js @@ -31,7 +31,7 @@ import { fetchPDFStitchedRecordForRedlines, fetchPDFStitchedRecordForResponsePackage, fetchPDFStitchedRecordForOIPCRedline, - fetchPDFStitchedRecordForOIPCReviewPackage, + fetchPDFStitchedRecordForOIPCRedlineReview, checkForRecordsChange, } from "../../../../apiManager/services/FOI/foiRecordServices"; import { @@ -228,8 +228,8 @@ export const RecordsLog = ({ let redlinePdfStitchStatus = useSelector( (state) => state.foiRequests.foiPDFStitchStatusForRedlines ); - let oipcReviewPackagePdfStitchedStatus = useSelector( - (state) => state.foiRequests.foiPDFStitchStatusForOipcReviewPackage + let oipcRedlineReviewPdfStitchedStatus = useSelector( + (state) => state.foiRequests.foiPDFStitchStatusForOipcRedlineReview ); let oipcRedlinePdfStitchedStatus = useSelector( (state) => state.foiRequests.foiPDFStitchStatusForOipcRedline @@ -244,8 +244,8 @@ export const RecordsLog = ({ let redlinePdfStitchedRecord = useSelector( (state) => state.foiRequests.foiPDFStitchedRecordForRedlines ); - let oipcReviewPackagePdfStitchedRecord = useSelector( - (state) => state.foiRequests.foiPDFStitchedRecordForOipcReviewPackage + let oipcRedlineReviewPdfStitchedRecord = useSelector( + (state) => state.foiRequests.foiPDFStitchedRecordForOipcRedlineReview ); let oipcRedlinePdfStitchedRecord = useSelector( (state) => state.foiRequests.foiPDFStitchedRecordForOipcRedline @@ -378,11 +378,11 @@ export const RecordsLog = ({ useState(false); const [isResponsePackageDownloadFailed, setIsResponsePackageDownloadFailed] = useState(false); - const [isOIPCReviewPackageReady, setIsOIPCReviewPackageReady] = + const [isOIPCRedlineReviewReady, setIsOIPCRedlineReviewReady] = useState(false); - const [isOIPCReviewPackageFailed, setIsOIPCReviewPackageFailed] = + const [isOIPCRedlineReviewFailed, setIsOIPCRedlineReviewFailed] = useState(false); - const [isOIPCReviewPackageInProgress, setIsOIPCReviewPackageInProgress] = + const [isOIPCRedlineReviewInProgress, setIsOIPCRedlineReviewInProgress] = useState(false); const [isOIPCRedlineReady, setIsOIPCRedlineReady] = useState(false); @@ -456,11 +456,11 @@ export const RecordsLog = ({ // Update OIPC Review Package PDF Stitch Status updateStatus( - oipcReviewPackagePdfStitchedStatus, - setIsOIPCReviewPackageInProgress, - setIsOIPCReviewPackageReady, - setIsOIPCReviewPackageFailed, - fetchPDFStitchedRecordForOIPCReviewPackage + oipcRedlineReviewPdfStitchedStatus, + setIsOIPCRedlineReviewInProgress, + setIsOIPCRedlineReviewReady, + setIsOIPCRedlineReviewFailed, + fetchPDFStitchedRecordForOIPCRedlineReview ); // Update Redline OIPC PDF Stitch Status updateStatus( @@ -475,7 +475,7 @@ export const RecordsLog = ({ redlinePdfStitchStatus, responsePackagePdfStitchStatus, oipcRedlinePdfStitchedStatus, - oipcReviewPackagePdfStitchedStatus, + oipcRedlineReviewPdfStitchedStatus, requestId, ministryId, ]); @@ -491,11 +491,11 @@ export const RecordsLog = ({ if (item.id === 4 && isOIPCRedlineReady) { item.disabled = false; } - if (item.id === 5 && isOIPCReviewPackageReady) { + if (item.id === 5 && isOIPCRedlineReviewReady) { item.disabled = false; } }); - }, [isRedlineDownloadReady, isResponsePackageDownloadReady, isOIPCRedlineReady, isOIPCReviewPackageReady]); + }, [isRedlineDownloadReady, isResponsePackageDownloadReady, isOIPCRedlineReady, isOIPCRedlineReviewReady]); const addAttachments = () => { setModalFor("add"); @@ -875,8 +875,8 @@ export const RecordsLog = ({ } else if (e.target.value === 4 && isOIPCRedlineReady) { const s3filepath = oipcRedlinePdfStitchedRecord?.finalpackagepath; handleDownloadZipFile(s3filepath, e.target.value); - } else if (e.target.value === 5 && isOIPCReviewPackageReady) { - const s3filepath = oipcReviewPackagePdfStitchedRecord?.finalpackagepath; + } else if (e.target.value === 5 && isOIPCRedlineReviewReady) { + const s3filepath = oipcRedlineReviewPdfStitchedRecord?.finalpackagepath; handleDownloadZipFile(s3filepath, e.target.value); } @@ -1057,9 +1057,9 @@ export const RecordsLog = ({ setIsOIPCRedlineReady(false); setIsOIPCRedlineFailed(true); } else if (itemid === 5) { - setIsOIPCReviewPackageInProgress(false); - setIsOIPCReviewPackageReady(false); - setIsOIPCReviewPackageFailed(true); + setIsOIPCRedlineReviewInProgress(false); + setIsOIPCRedlineReviewReady(false); + setIsOIPCRedlineReviewFailed(true); } }; @@ -1069,7 +1069,7 @@ export const RecordsLog = ({ (itemid === 2 && isRedlineDownloadReady) || (itemid === 3 && isResponsePackageDownloadReady) || (itemid === 4 && isOIPCRedlineReady) || - (itemid === 5 && isOIPCReviewPackageReady) + (itemid === 5 && isOIPCRedlineReviewReady) ); }; @@ -1079,7 +1079,7 @@ export const RecordsLog = ({ (itemid === 2 && isRedlineDownloadFailed) || (itemid === 3 && isResponsePackageDownloadFailed) || (itemid === 4 && isOIPCRedlineFailed) || - (itemid === 5 && isOIPCReviewPackageFailed) + (itemid === 5 && isOIPCRedlineReviewFailed) ); }; @@ -1089,7 +1089,7 @@ export const RecordsLog = ({ (itemid === 2 && isRedlineDownloadInProgress) || (itemid === 3 && isResponsePackageDownloadInProgress) || (itemid === 4 && isOIPCRedlineInProgress) || - (itemid === 5 && isOIPCReviewPackageInProgress) + (itemid === 5 && isOIPCRedlineReviewInProgress) ); }; @@ -1639,12 +1639,6 @@ export const RecordsLog = ({ ); }; - console.log(responsePackagePdfStitchedRecord); - console.log(responsePackagePdfStitchStatus); - console.log("BREAK") - console.log(oipcReviewPackagePdfStitchedRecord); - console.log(oipcReviewPackagePdfStitchedStatus); - return (
{isAttachmentLoading ? ( diff --git a/forms-flow-web/src/modules/FOI/foiRequestsReducer.js b/forms-flow-web/src/modules/FOI/foiRequestsReducer.js index 6108546c8..4da4d7096 100644 --- a/forms-flow-web/src/modules/FOI/foiRequestsReducer.js +++ b/forms-flow-web/src/modules/FOI/foiRequestsReducer.js @@ -57,13 +57,13 @@ const initialState = { }, foiPDFStitchedRecordForHarms: {}, foiPDFStitchedRecordForRedlines: {}, - foiPDFStitchedRecordForOipcReviewPackage: {}, + foiPDFStitchedRecordForOipcRedlineReview: {}, foiPDFStitchedRecordForOipcRedline: {}, foiPDFStitchedRecordForResponsePackage: {}, foiPDFStitchStatusForHarms: "not started", foiPDFStitchStatusForRedlines: "not started", foiPDFStitchStatusForResponsePackage: "not started", - foiPDFStitchStatusForOipcReviewPackage: "not started", + foiPDFStitchStatusForOipcRedlineReview: "not started", foiPDFStitchStatusForOipcRedline: "not started", foiRequestCFRForm: { overallsuggestions: "", @@ -272,10 +272,10 @@ const foiRequests = (state = initialState, action) => { ...state, foiPDFStitchedRecordForResponsePackage: action.payload, }; - case FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_RECORD_FOR_OIPCREVIEWPACKAGE: + case FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_RECORD_FOR_OIPCREDLINEREVIEW: return { ...state, - foiPDFStitchedRecordForOipcReviewPackage: action.payload, + foiPDFStitchedRecordForOipcRedlineReview: action.payload, }; case FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_RECORD_FOR_OIPCREDLINE: return { @@ -288,8 +288,8 @@ const foiRequests = (state = initialState, action) => { return { ...state, foiPDFStitchStatusForRedlines: action.payload }; case FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_STATUS_FOR_RESPONSEPACKAGE: return { ...state, foiPDFStitchStatusForResponsePackage: action.payload }; - case FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_STATUS_FOR_OIPCREVIEWPACKAGE: - return { ...state, foiPDFStitchStatusForOipcReviewPackage: action.payload }; + case FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_STATUS_FOR_OIPCREDLINEREVIEW: + return { ...state, foiPDFStitchStatusForOipcRedlineReview: action.payload }; case FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_STATUS_FOR_OIPCREDLINE: return { ...state, foiPDFStitchStatusForOipcRedline: action.payload }; case FOI_ACTION_CONSTANTS.FOI_REQUEST_CFR_FORM: From ee2591320d4ca0207866798e5bd9f7e3cb865316 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Wed, 20 Dec 2023 15:53:25 -0800 Subject: [PATCH 149/238] Changing of download menu item naming in FE --- forms-flow-web/src/constants/FOI/enum.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/forms-flow-web/src/constants/FOI/enum.js b/forms-flow-web/src/constants/FOI/enum.js index 24020abc3..ec0ea2aac 100644 --- a/forms-flow-web/src/constants/FOI/enum.js +++ b/forms-flow-web/src/constants/FOI/enum.js @@ -170,8 +170,8 @@ const RecordsDownloadList = [ { id: 1, label: "Download for Harms", disabled: true }, { id: 2, label: "Download Redline for Sign Off", disabled: true }, { id: 3, label: "Download Final Package", disabled: true }, - { id: 4, label: "Download Redline for OIPC Sign Off", disabled: true }, - { id: 5, label: "Download Redline for OIPC Review", disabled: true }, + { id: 4, label: "Download OIPC Redline for Sign Off", disabled: true }, + { id: 5, label: "Download OIPC Redline for OIPC Review", disabled: true }, ]; const RecordDownloadCategory = Object.freeze({ From b0a5a70beffa3e8ff8d668e6543e3c6a465296bf Mon Sep 17 00:00:00 2001 From: "sumathi.thirumani" Date: Thu, 21 Dec 2023 11:03:24 -0800 Subject: [PATCH 150/238] Changes to send reminder notifications; only when outcome is not taken. --- request-management-api/request_api/models/FOIMinistryRequests.py | 1 + 1 file changed, 1 insertion(+) diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index 8f127614a..7d45eb6e2 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -809,6 +809,7 @@ def getupcomingoipcduerecords(cls): order by fpa.foiministryrequestid , fpa.version desc) fma on frd.foiministryrequest_id = fma.foiministryrequestid and frd.foiministryrequestversion_id = fma.foiministryrequestversion and fma.requeststatusid not in (5,6,4,11,3,15) and (frd.inquiryattributes ->> 'inquirydate')::date between NOW() - INTERVAL '7 DAY' AND NOW() + INTERVAL '7 DAY' + and frd.outcomeid is null order by frd.foiministryrequest_id , frd.foiministryrequestversion_id desc;""" rs = db.session.execute(text(sql)) for row in rs: From 30e6474325269dbe075fa91039131a6245e19f2e Mon Sep 17 00:00:00 2001 From: "sumathi.thirumani" Date: Thu, 21 Dec 2023 13:48:11 -0800 Subject: [PATCH 151/238] Changes to send reminder notifications; only when outcome is not taken. --- .../request_api/models/FOIMinistryRequests.py | 2 ++ .../services/foirequest/requestservicebuilder.py | 9 ++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index 7d45eb6e2..acf0f870f 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -808,6 +808,8 @@ def getupcomingoipcduerecords(cls): from "FOIMinistryRequests" fpa order by fpa.foiministryrequestid , fpa.version desc) fma on frd.foiministryrequest_id = fma.foiministryrequestid and frd.foiministryrequestversion_id = fma.foiministryrequestversion and fma.requeststatusid not in (5,6,4,11,3,15) + and inquiryattributes is not null + and frd.inquiryattributes ->> 'inquirydate' not in ('','null') and (frd.inquiryattributes ->> 'inquirydate')::date between NOW() - INTERVAL '7 DAY' AND NOW() + INTERVAL '7 DAY' and frd.outcomeid is null order by frd.foiministryrequest_id , frd.foiministryrequestversion_id desc;""" diff --git a/request-management-api/request_api/services/foirequest/requestservicebuilder.py b/request-management-api/request_api/services/foirequest/requestservicebuilder.py index dd1a0516b..bb1fbc262 100644 --- a/request-management-api/request_api/services/foirequest/requestservicebuilder.py +++ b/request-management-api/request_api/services/foirequest/requestservicebuilder.py @@ -152,11 +152,18 @@ def prepareoipc(self, requestschema, ministryrequestid, version, userid): oipcreview.receiveddate = oipc["receiveddate"] if oipc["receiveddate"] not in (None, "") else None oipcreview.closeddate = oipc["closeddate"] if oipc["closeddate"] not in (None, "") else None if oipc["isinquiry"] == True: - oipcreview.inquiryattributes = oipc["inquiryattributes"] + oipcreview.inquiryattributes = self.__formatoipcattributes(oipc["inquiryattributes"]) oipcreview.createdby=userid oipcreview.created_at= datetime2.now().isoformat() oipcarr.append(oipcreview) return oipcarr + + def __formatoipcattributes(self, inquiryattributes): + if inquiryattributes not in (None, ""): + if (inquiryattributes["inquirydate"]) in ("","null"): + inquiryattributes["inquirydate"] = None + print(inquiryattributes) + return inquiryattributes def isNotBlankorNone(self, dataschema, key, location): From 4e10941163c4ffca73900eca050e46b2a0321417 Mon Sep 17 00:00:00 2001 From: "sumathi.thirumani" Date: Thu, 21 Dec 2023 13:54:11 -0800 Subject: [PATCH 152/238] Changes to send reminder notifications; only when outcome is not taken. --- .../services/foirequest/requestservicebuilder.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/request-management-api/request_api/services/foirequest/requestservicebuilder.py b/request-management-api/request_api/services/foirequest/requestservicebuilder.py index bb1fbc262..eef873754 100644 --- a/request-management-api/request_api/services/foirequest/requestservicebuilder.py +++ b/request-management-api/request_api/services/foirequest/requestservicebuilder.py @@ -159,10 +159,8 @@ def prepareoipc(self, requestschema, ministryrequestid, version, userid): return oipcarr def __formatoipcattributes(self, inquiryattributes): - if inquiryattributes not in (None, ""): - if (inquiryattributes["inquirydate"]) in ("","null"): - inquiryattributes["inquirydate"] = None - print(inquiryattributes) + if inquiryattributes not in (None, "") and inquiryattributes["inquirydate"] in ("","null"): + inquiryattributes["inquirydate"] = None return inquiryattributes From 34d922366659652f7aef81d1f6e7ab74894d2356 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Thu, 21 Dec 2023 16:30:26 -0800 Subject: [PATCH 153/238] adjusted api endpoint call --- forms-flow-web/src/apiManager/endpoints/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/forms-flow-web/src/apiManager/endpoints/index.js b/forms-flow-web/src/apiManager/endpoints/index.js index f8aeb111d..4a03e6cc0 100644 --- a/forms-flow-web/src/apiManager/endpoints/index.js +++ b/forms-flow-web/src/apiManager/endpoints/index.js @@ -135,8 +135,8 @@ const API = { FOI_DOWNLOAD_RECORDS_FOR_RESPONSEPACKAGE: `${FOI_BASE_API_URL}/api/foirecord//ministryrequest//download/responsepackage`, FOI_PDF_STITCH_STATUS_FOR_RESPONSEPACKAGE: `${FOI_BASE_API_URL}/api/foirecord//ministryrequest//responsepackage/pdfstitchjobstatus`, - FOI_DOWNLOAD_RECORDS_FOR_OIPCREDLINEREVIEW: `${FOI_BASE_API_URL}/api/foirecord//ministryrequest//download/oipcredlinereview`, - FOI_PDF_STITCH_STATUS_FOR_OIPCREDLINEREVIEW: `${FOI_BASE_API_URL}/api/foirecord//ministryrequest//oipcredlinereview/pdfstitchjobstatus`, + FOI_DOWNLOAD_RECORDS_FOR_OIPCREDLINEREVIEW: `${FOI_BASE_API_URL}/api/foirecord//ministryrequest//download/oipcreviewredline`, + FOI_PDF_STITCH_STATUS_FOR_OIPCREDLINEREVIEW: `${FOI_BASE_API_URL}/api/foirecord//ministryrequest//oipcreviewredline/pdfstitchjobstatus`, FOI_DOWNLOAD_RECORDS_FOR_OIPCREDLINE: `${FOI_BASE_API_URL}/api/foirecord//ministryrequest//download/oipcredline`, FOI_PDF_STITCH_STATUS_FOR_OIPCREDLINE: `${FOI_BASE_API_URL}/api/foirecord//ministryrequest//oipcredline/pdfstitchjobstatus`, From 81d2fa83ed78271db8459887e5484ffd3704b333 Mon Sep 17 00:00:00 2001 From: divyav-aot Date: Fri, 22 Dec 2023 14:06:50 -0500 Subject: [PATCH 154/238] integrated keyword serch --- .../src/apiManager/endpoints/index.js | 1 + .../FOI/foiApplicantProfileService.js | 138 ++++++++++++++++++ .../services/FOI/foiRequestServices.js | 107 -------------- .../FOI/FOIRequest/ApplicantProfileModal.js | 56 ++++++- .../models/FOIRequestApplicants.py | 61 +++++++- .../request_api/resources/foiapplicant.py | 2 - .../request_api/services/applicantservice.py | 4 + 7 files changed, 254 insertions(+), 115 deletions(-) create mode 100644 forms-flow-web/src/apiManager/services/FOI/foiApplicantProfileService.js diff --git a/forms-flow-web/src/apiManager/endpoints/index.js b/forms-flow-web/src/apiManager/endpoints/index.js index 2ed298394..d13c7fd7b 100644 --- a/forms-flow-web/src/apiManager/endpoints/index.js +++ b/forms-flow-web/src/apiManager/endpoints/index.js @@ -41,6 +41,7 @@ const API = { FOI_GET_REQUEST_APPLICANTS: `${FOI_BASE_API_URL}/api/foiapplicants/`, FOI_SAVE_REQUEST_APPLICANT_INFO: `${FOI_BASE_API_URL}/api/foiapplicants/save`, + FOI_REQUEST_APPLICANTS_SEARCH_KEYWORDS: `${FOI_BASE_API_URL}/api/foiapplicants/search`, FOI_GET_PROGRAMAREADIVISIONS: `${FOI_BASE_API_URL}/api/foiadmin/divisions`, FOI_POST_PROGRAMAREADIVISION: `${FOI_BASE_API_URL}/api/foiadmin/division`, diff --git a/forms-flow-web/src/apiManager/services/FOI/foiApplicantProfileService.js b/forms-flow-web/src/apiManager/services/FOI/foiApplicantProfileService.js new file mode 100644 index 000000000..6fbe6d932 --- /dev/null +++ b/forms-flow-web/src/apiManager/services/FOI/foiApplicantProfileService.js @@ -0,0 +1,138 @@ +import { + httpPOSTRequest, + httpGETRequest, +} from "../../httpRequestHandler"; +import API from "../../endpoints"; +import { + serviceActionError, + setRestrictedReqTaglist +} from "../../../actions/FOI/foiRequestActions"; +import { catchError, fnDone} from './foiServicesUtil'; +import UserService from "../../../services/UserService"; +import { replaceUrl } from "../../../helper/FOI/helper"; + +export const fetchPotentialApplicants = (firstname, lastname, email, phone, ...rest) => { + // console.log("fetch applicants" + firstname) + // console.log(firstname) + // console.log(lastname) + + const done = fnDone(rest); + // await new Promise(resolve => {setTimeout(resolve, 3000)}); + // done(null, [ + // { id: 1, lastName: 'Snow', firstName: 'Jon', age: 35 }, + // { id: 2, lastName: 'Lannister', firstName: 'Cersei', age: 42 }, + // { id: 3, lastName: 'Lannister', firstName: 'Jaime', age: 45 }, + // { id: 4, lastName: 'Stark', firstName: 'Arya', age: 16 }, + // { id: 5, lastName: 'Targaryen', firstName: 'Daenerys', age: null }, + // { id: 7, lastName: 'Clifford', firstName: 'Ferrara', age: 44 }, + // { id: 8, lastName: 'Frances', firstName: 'Rossini', age: 36 }, + // { id: 9, lastName: 'Roxie', firstName: 'Harvey', age: 65 }, + // ]); + // return; + const apiUrlgetRequestDetails = replaceUrl( + API.FOI_GET_REQUEST_APPLICANTS, + "", + email + ); + return (dispatch) => { + httpGETRequest(apiUrlgetRequestDetails, {}, UserService.getToken()) + .then((res) => { + if (res.data) { + done(null, res.data) + } else { + dispatch(serviceActionError(res)); + throw new Error(`Error in fetching potential applicants`) + } + }) + .catch((error) => { + catchError(error, dispatch); + }); + }; +}; + +export const fetchApplicantInfo = async (firstname, ...rest) => { + + const done = fnDone(rest); + done(null, + { id: 1, lastName: 'Snow', firstName: 'Jon', age: 35, email: 'jon.snow@gmail.com', + additionalPersonalInfo: {birthDate: "2023-12-07"}, + requestHistory: [{requestId: "EDU-2023-234345", receivedDate: "2023-12-07", currentState: "Open", requestDescription: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but als"}] + } + ); + return; + // const apiUrlgetRequestDetails = replaceUrl(replaceUrl( + // API.FOI_MINISTRYVIEW_REQUEST_API, + // "", + // requestId + // ), "", ministryId); + // return (dispatch) => { + // httpGETRequest(apiUrlgetRequestDetails, {}, UserService.getToken()) + // .then((res) => { + // if (res.data) { + // const foiRequest = res.data; + // dispatch(clearMinistryViewRequestDetails({})); + // dispatch(setFOIMinistryViewRequestDetail(foiRequest)); + // dispatch(fetchFOIMinistryAssignedToList(foiRequest.selectedMinistries[0].code.toLowerCase())); + // dispatch(setFOILoader(false)); + // } else { + // dispatch(serviceActionError(res)); + // dispatch(setFOILoader(false)); + // throw new Error(`Error in fetching ministry request details for request# ${requestId} ministry# ${ministryId}`) + // } + // }) + // .catch((error) => { + // catchError(error, dispatch); + // }); + // }; +}; + +export const fetchApplicantContactHistory = (...rest) => { + const done = fnDone(rest); + done(null, + [{ + field: "Email", + value: "a@b.ca", + date: "2023-12-11", + username: "foiintake@idir", + }] + ); +} + +export const saveApplicantInfo = (applicant, ...rest) => { + const done = fnDone(rest); + const apiUrlgetRequestDetails = API.FOI_SAVE_REQUEST_APPLICANT_INFO; + return (dispatch) => { + httpPOSTRequest(apiUrlgetRequestDetails, applicant, UserService.getToken()) + .then((res) => { + if (res.data) { + dispatch(setRestrictedReqTaglist(res.data)); + done(null, res.data); + } else { + dispatch(serviceActionError(res)); + throw new Error(`Error in saving applicant`); + } + }) + .catch((error) => { + catchError(error, dispatch); + }); + } +}; + +export const fetchApplicantProfileByKeyword = (keywords, ...rest) => { + const done = fnDone(rest); + const apiUrl = API.FOI_REQUEST_APPLICANTS_SEARCH_KEYWORDS; + return (dispatch) => { + httpPOSTRequest(apiUrl, keywords, UserService.getToken()) + .then((res) => { + if (res.data) { + done(null, res.data) + } else { + dispatch(serviceActionError(res)); + throw new Error(`Error in fetching potential applicants`) + } + }) + .catch((error) => { + catchError(error, dispatch); + }); + } +}; \ No newline at end of file diff --git a/forms-flow-web/src/apiManager/services/FOI/foiRequestServices.js b/forms-flow-web/src/apiManager/services/FOI/foiRequestServices.js index 563acf7e5..e607d67cb 100644 --- a/forms-flow-web/src/apiManager/services/FOI/foiRequestServices.js +++ b/forms-flow-web/src/apiManager/services/FOI/foiRequestServices.js @@ -525,111 +525,4 @@ export const fetchRestrictedRequestCommentTagList = (requestid, ministryId, ...r catchError(error, dispatch); }); } -}; - -export const fetchPotentialApplicants = (firstname, lastname, email, phone, ...rest) => { - // console.log("fetch applicants" + firstname) - // console.log(firstname) - // console.log(lastname) - - const done = fnDone(rest); - // await new Promise(resolve => {setTimeout(resolve, 3000)}); - // done(null, [ - // { id: 1, lastName: 'Snow', firstName: 'Jon', age: 35 }, - // { id: 2, lastName: 'Lannister', firstName: 'Cersei', age: 42 }, - // { id: 3, lastName: 'Lannister', firstName: 'Jaime', age: 45 }, - // { id: 4, lastName: 'Stark', firstName: 'Arya', age: 16 }, - // { id: 5, lastName: 'Targaryen', firstName: 'Daenerys', age: null }, - // { id: 7, lastName: 'Clifford', firstName: 'Ferrara', age: 44 }, - // { id: 8, lastName: 'Frances', firstName: 'Rossini', age: 36 }, - // { id: 9, lastName: 'Roxie', firstName: 'Harvey', age: 65 }, - // ]); - // return; - const apiUrlgetRequestDetails = replaceUrl( - API.FOI_GET_REQUEST_APPLICANTS, - "", - email - ); - return (dispatch) => { - httpGETRequest(apiUrlgetRequestDetails, {}, UserService.getToken()) - .then((res) => { - if (res.data) { - done(null, res.data) - } else { - dispatch(serviceActionError(res)); - throw new Error(`Error in fetching potential applicants`) - } - }) - .catch((error) => { - catchError(error, dispatch); - }); - }; -}; - -export const fetchApplicantInfo = async (firstname, ...rest) => { - - const done = fnDone(rest); - done(null, - { id: 1, lastName: 'Snow', firstName: 'Jon', age: 35, email: 'jon.snow@gmail.com', - additionalPersonalInfo: {birthDate: "2023-12-07"}, - requestHistory: [{requestId: "EDU-2023-234345", receivedDate: "2023-12-07", currentState: "Open", requestDescription: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but als"}] - } - ); - return; - // const apiUrlgetRequestDetails = replaceUrl(replaceUrl( - // API.FOI_MINISTRYVIEW_REQUEST_API, - // "", - // requestId - // ), "", ministryId); - // return (dispatch) => { - // httpGETRequest(apiUrlgetRequestDetails, {}, UserService.getToken()) - // .then((res) => { - // if (res.data) { - // const foiRequest = res.data; - // dispatch(clearMinistryViewRequestDetails({})); - // dispatch(setFOIMinistryViewRequestDetail(foiRequest)); - // dispatch(fetchFOIMinistryAssignedToList(foiRequest.selectedMinistries[0].code.toLowerCase())); - // dispatch(setFOILoader(false)); - // } else { - // dispatch(serviceActionError(res)); - // dispatch(setFOILoader(false)); - // throw new Error(`Error in fetching ministry request details for request# ${requestId} ministry# ${ministryId}`) - // } - // }) - // .catch((error) => { - // catchError(error, dispatch); - // }); - // }; -}; - -export const fetchApplicantContactHistory = (...rest) => { - const done = fnDone(rest); - done(null, - [{ - field: "Email", - value: "a@b.ca", - date: "2023-12-11", - username: "foiintake@idir", - }] - ); -} - -export const saveApplicantInfo = (applicant, ...rest) => { - const done = fnDone(rest); - const apiUrlgetRequestDetails = API.FOI_SAVE_REQUEST_APPLICANT_INFO; - return (dispatch) => { - httpPOSTRequest(apiUrlgetRequestDetails, applicant, UserService.getToken()) - .then((res) => { - if (res.data) { - dispatch(setRestrictedReqTaglist(res.data)); - done(null, res.data); - } else { - dispatch(serviceActionError(res)); - throw new Error(`Error in saving applicant`); - } - }) - .catch((error) => { - catchError(error, dispatch); - }); - } }; \ No newline at end of file diff --git a/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js b/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js index b8f09d752..cf3c4671b 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js @@ -16,7 +16,7 @@ import SearchIcon from "@material-ui/icons/Search"; import InputAdornment from "@mui/material/InputAdornment"; import InputBase from "@mui/material/InputBase"; import Grid from "@mui/material/Grid"; -import { fetchPotentialApplicants, fetchApplicantInfo, fetchApplicantContactHistory, saveApplicantInfo } from "../../../apiManager/services/FOI/foiRequestServices"; +import { fetchPotentialApplicants, fetchApplicantInfo, fetchApplicantContactHistory, saveApplicantInfo, fetchApplicantProfileByKeyword } from "../../../apiManager/services/FOI/foiApplicantProfileService"; import AddressContactDetails from "./AddressContanctInfo"; import ApplicantDetails from "./ApplicantDetails" import AdditionalApplicantDetails from "./AdditionalApplicantDetails"; @@ -34,6 +34,7 @@ import Typography from '@material-ui/core/Typography'; import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import { StateEnum } from "../../../constants/FOI/statusEnum"; import { setFOIRequestApplicantProfile } from "../../../actions/FOI/foiRequestActions"; +import { toast } from "react-toastify"; const useStyles = makeStyles((theme) => ({ root: { @@ -203,9 +204,60 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { } } + const createKeywordJSON = (keyword) => { + const keywordJSON = { + "keywords": {} + } + const mobileNumberRegex = /^(\+\d{1,3}[-.●]?)?\(?\d{3}\)?[-.●]?\d{3}[-.●]?\d{4}$/; + const stringRegex = /^[A-Za-z0-9\s.@!#$%^&*()\-_=+[\]{};:'",<.>/?\\|]+$/; + const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + const isValidEmail = emailRegex.test(keyword); + const isValidNumber = mobileNumberRegex.test(keyword); + const isValidString = stringRegex.test(keyword) + if (isValidEmail) { + keywordJSON.keywords["email"] = keyword; + } + if (isValidNumber) { + keywordJSON.keywords["homephone"] = keyword; + keywordJSON.keywords["workphone"] = keyword; + keywordJSON.keywords["workphone2"] = keyword; + keywordJSON.keywords["mobilephone"] = keyword; + } + if (isValidString) { + keywordJSON.keywords["firstname"] = keyword; + keywordJSON.keywords["lastname"] = keyword; + keywordJSON.keywords["email"] = keyword; + } + return keywordJSON; + } + const onSearchEnter = (e) => { if (searchMode === 'manual' && e.key === 'Enter') { - console.log("search"); + const keywordJSON = createKeywordJSON(e.target.value) + setIsLoading(true); + dispatch(fetchApplicantProfileByKeyword( + keywordJSON, + (err, res) => { + if (!err) { + setRows(res); + setIsLoading(false); + } + else { + toast.error( + "Temporarily unable to fetch applicant profiles. Please try again in a few minutes.", + { + position: "top-right", + autoClose: 3000, + hideProgressBar: true, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + } + ); + } + + })) } } diff --git a/request-management-api/request_api/models/FOIRequestApplicants.py b/request-management-api/request_api/models/FOIRequestApplicants.py index 088d3ad88..f1b0e292c 100644 --- a/request-management-api/request_api/models/FOIRequestApplicants.py +++ b/request-management-api/request_api/models/FOIRequestApplicants.py @@ -240,7 +240,7 @@ def getapplicantbyemail(cls, email): province.foirequestversion_id == FOIRequest.version, province.contacttypeid == 2, province.contactinformation is not None, - city.dataformat == 'province'), + province.dataformat == 'province'), isouter=True ).join( country, @@ -249,7 +249,7 @@ def getapplicantbyemail(cls, email): country.foirequestversion_id == FOIRequest.version, country.contacttypeid == 2, country.contactinformation is not None, - city.dataformat == 'country'), + country.dataformat == 'country'), isouter=True ).join( postal, @@ -258,7 +258,7 @@ def getapplicantbyemail(cls, email): postal.foirequestversion_id == FOIRequest.version, postal.contacttypeid == 2, postal.contactinformation is not None, - city.dataformat == 'postal'), + postal.dataformat == 'postal'), isouter=True ).join( personalemployeenumber, @@ -305,6 +305,10 @@ def getapplicantbyemail(cls, email): func.array_agg(subquery_all.c.applicantcategory).label('applicantcategory'), func.array_agg(subquery_all.c.email).label('email'), func.array_agg(subquery_all.c.address).label('address'), + func.array_agg(subquery_all.c.city).label('city'), + func.array_agg(subquery_all.c.province).label('province'), + func.array_agg(subquery_all.c.postal).label('postal'), + func.array_agg(subquery_all.c.country).label('country'), func.array_agg(subquery_all.c.homephone).label('homephone'), func.array_agg(subquery_all.c.workphone).label('workphone'), func.array_agg(subquery_all.c.workphone2).label('workphone2'), @@ -336,6 +340,11 @@ def searchapplicant(cls, keywords): contactmobilephone = aliased(FOIRequestContactInformation) contactother = aliased(FOIRequestContactInformation) + city = aliased(FOIRequestContactInformation) + province = aliased(FOIRequestContactInformation) + postal = aliased(FOIRequestContactInformation) + country = aliased(FOIRequestContactInformation) + #aliase for getting personal attributes personalemployeenumber = aliased(FOIRequestPersonalAttribute) personalcorrectionnumber = aliased(FOIRequestPersonalAttribute) @@ -364,6 +373,10 @@ def searchapplicant(cls, keywords): ApplicantCategory.name.label('applicantcategory'), contactemail.contactinformation.label('email'), contactaddress.contactinformation.label('address'), + city.contactinformation.label('city'), + province.contactinformation.label('province'), + postal.contactinformation.label('postal'), + country.contactinformation.label('country'), contacthomephone.contactinformation.label('homephone'), contactworkphone.contactinformation.label('workphone'), contactworkphone2.contactinformation.label('workphone2'), @@ -455,6 +468,42 @@ def searchapplicant(cls, keywords): contactother.contacttypeid == 7, contactother.contactinformation is not None), isouter=True + ).join( + city, + and_( + city.foirequest_id == FOIRequest.foirequestid, + city.foirequestversion_id == FOIRequest.version, + city.contacttypeid == 2, + city.contactinformation is not None, + city.dataformat == 'city'), + isouter=True + ).join( + province, + and_( + province.foirequest_id == FOIRequest.foirequestid, + province.foirequestversion_id == FOIRequest.version, + province.contacttypeid == 2, + province.contactinformation is not None, + province.dataformat == 'province'), + isouter=True + ).join( + country, + and_( + country.foirequest_id == FOIRequest.foirequestid, + country.foirequestversion_id == FOIRequest.version, + country.contacttypeid == 2, + country.contactinformation is not None, + country.dataformat == 'country'), + isouter=True + ).join( + postal, + and_( + postal.foirequest_id == FOIRequest.foirequestid, + postal.foirequestversion_id == FOIRequest.version, + postal.contacttypeid == 2, + postal.contactinformation is not None, + postal.dataformat == 'postal'), + isouter=True ).join( personalemployeenumber, and_( @@ -500,6 +549,10 @@ def searchapplicant(cls, keywords): func.array_agg(subquery_all.c.applicantcategory).label('applicantcategory'), func.array_agg(subquery_all.c.email).label('email'), func.array_agg(subquery_all.c.address).label('address'), + func.array_agg(subquery_all.c.city).label('city'), + func.array_agg(subquery_all.c.province).label('province'), + func.array_agg(subquery_all.c.postal).label('postal'), + func.array_agg(subquery_all.c.country).label('country'), func.array_agg(subquery_all.c.homephone).label('homephone'), func.array_agg(subquery_all.c.workphone).label('workphone'), func.array_agg(subquery_all.c.workphone2).label('workphone2'), @@ -549,5 +602,5 @@ class ApplicantProfileSchema(ma.Schema): class Meta: fields = ('foirequestapplicantid','firstname','middlename','lastname','alsoknownas','dob', 'businessname','applicantversion','foirequestid','foirequestversion','requesttype', - 'applicantcategory','email','address','homephone','workphone','workphone2','mobilephone', + 'applicantcategory','email','address','city','province','postal','country','homephone','workphone','workphone2','mobilephone', 'othercontactinfo','employeenumber','correctionnumber','phn') diff --git a/request-management-api/request_api/resources/foiapplicant.py b/request-management-api/request_api/resources/foiapplicant.py index 0ff131d71..05fb4ff8d 100644 --- a/request-management-api/request_api/resources/foiapplicant.py +++ b/request-management-api/request_api/resources/foiapplicant.py @@ -50,8 +50,6 @@ class FOIApplicants(Resource): @auth.isiao @cors_preflight('GET,OPTIONS') def get(email=None): - print(email) - if email is None or email == "": return {'status': False, 'message':EXCEPTION_MESSAGE_BAD_REQUEST}, 400 try: diff --git a/request-management-api/request_api/services/applicantservice.py b/request-management-api/request_api/services/applicantservice.py index 799d58bcc..ed5cdaeb3 100644 --- a/request-management-api/request_api/services/applicantservice.py +++ b/request-management-api/request_api/services/applicantservice.py @@ -89,6 +89,10 @@ def __prepareapplicant(self, applicant): # 'category': applicant["applicantcategory"], 'email': self.__first_not_null(applicant["email"]), 'address': self.__first_not_null(applicant["address"]), + 'city': self.__first_not_null(applicant["city"]), + 'province': self.__first_not_null(applicant["province"]), + 'postal': self.__first_not_null(applicant["postal"]), + 'country': self.__first_not_null(applicant["country"]), 'phonePrimary': self.__first_not_null(applicant["homephone"]), 'workPhonePrimary': self.__first_not_null(applicant["workphone"]), 'workPhoneSecondary': self.__first_not_null(applicant["workphone2"]), From 8da7d85fd3051a35c3e62397f494b07f0c56174d Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Wed, 27 Dec 2023 20:34:34 -0800 Subject: [PATCH 155/238] Fix filter to remove closed OIPC requests from ministry queue --- .../request_api/models/FOIMinistryRequests.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index acf0f870f..7af6981cd 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -361,6 +361,9 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us #aliase for getting ministry restricted flag from FOIRestrictedMinistryRequest ministry_restricted_requests = aliased(FOIRestrictedMinistryRequest) + #alias for filtering closed OIPC requests (where outcome is selected) + oipc_requests = aliased(FOIRequestOIPC) + #filter/search if(len(filterfields) > 0 and keyword is not None): filtercondition = [] @@ -564,8 +567,20 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us SubjectCode, SubjectCode.subjectcodeid == FOIMinistryRequestSubjectCode.subjectcodeid, isouter=True - ).filter(or_(FOIMinistryRequest.requeststatusid != 3, and_(FOIMinistryRequest.isoipcreview == True, FOIMinistryRequest.requeststatusid == 3))) - + ).filter( + or_( + FOIMinistryRequest.requeststatusid != 3, + and_( + FOIMinistryRequest.isoipcreview == True, + FOIMinistryRequest.requeststatusid == 3, + and_( + FOIMinistryRequest.foiministryrequestid == oipc_requests.foiministryrequest_id, + FOIMinistryRequest.version == oipc_requests.foiministryrequestversion_id, + oipc_requests.outcome == None + ) + ) + ) + ) if(additionalfilter == 'watchingRequests'): From 0676859e461e542ff3f823be09e6717bf1feb7c6 Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Wed, 27 Dec 2023 20:35:28 -0800 Subject: [PATCH 156/238] Add loading modal when removing OIPC flag --- forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index 5c7d8db01..add632bb2 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -670,6 +670,7 @@ const FOIRequest = React.memo(({ userDetail }) => { }; const saveOIPCNoReview = () => { + const toastID = toast.loading("Saving request with removed OIPC review...") removeAllOIPCs(); setIsOIPCReview(false); dispatch( @@ -678,8 +679,11 @@ const FOIRequest = React.memo(({ userDetail }) => { ministryId, (err, _res) => { if(!err) { - toast.success("OIPC details have been saved successfully.", { + toast.update(toastID, { + type: "success", + render: "OIPC details have been saved successfully.", position: "top-right", + isLoading: false, autoClose: 3000, hideProgressBar: true, closeOnClick: true, From 857ad9735085684ebc4d18645ffa3dee3a91da0c Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Wed, 27 Dec 2023 20:36:45 -0800 Subject: [PATCH 157/238] Save request when deleting OIPC detail --- .../OIPCDetails/RemoveOIPCModal.jsx | 49 ++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/RemoveOIPCModal.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/RemoveOIPCModal.jsx index 878d8bea8..ab1957fc2 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/RemoveOIPCModal.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/RemoveOIPCModal.jsx @@ -5,6 +5,11 @@ import DialogContentText from '@material-ui/core/DialogContentText'; import DialogTitle from '@material-ui/core/DialogTitle'; import CloseIcon from '@material-ui/icons/Close'; import IconButton from '@material-ui/core/IconButton'; +import useOIPCHook from './oipcHook'; +import { deleteOIPCDetails } from '../../../../apiManager/services/FOI/foiRequestServices'; +import { useDispatch } from 'react-redux'; +import { toast } from "react-toastify"; +import { useParams } from "react-router-dom"; const RemoveOIPCModal= ({ showModal, @@ -12,10 +17,52 @@ const RemoveOIPCModal= ({ setShowModal, oipc, }) =>{ + const dispatch = useDispatch(); + const { requestId, ministryId } = useParams(); + const { setIsOIPCReview, removeAllOIPCs } = useOIPCHook(); + const saveOIPCNoReview = () => { + const toastID = toast.loading("Saving request with removed OIPC review...") + removeAllOIPCs(); + setIsOIPCReview(false); + dispatch( + deleteOIPCDetails( + requestId, + ministryId, + (err, _res) => { + if(!err) { + toast.update(toastID, { + type: "success", + render: "Removal of OIPC review has been saved successfully.", + position: "top-right", + isLoading: false, + autoClose: 3000, + hideProgressBar: true, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + }); + } else { + toast.error( + "Temporarily unable to save the request with removed OIPC review. Please try again in a few minutes.", + { + position: "top-right", + autoClose: 3000, + hideProgressBar: true, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + } + );} + }) + ) + } const handleSave = () => { setShowModal(false); removeOIPC(oipc.id) + saveOIPCNoReview(); }; const handleClose = () => { setShowModal(false); @@ -39,7 +86,7 @@ const RemoveOIPCModal= ({ - Are you sure you want to delete this OIPC Review? + Are you sure you want to delete this OIPC Review? The request will be saved automatically if you continue. From d8e4e08c1fe8253b458baccc5ff6de8854ed4dbd Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Wed, 27 Dec 2023 20:37:01 -0800 Subject: [PATCH 158/238] Fix missing modal heading --- .../src/components/FOI/customComponents/RequestFlag.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js b/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js index 1fca647b0..65dd5fd6c 100644 --- a/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js +++ b/forms-flow-web/src/components/FOI/customComponents/RequestFlag.js @@ -80,7 +80,7 @@ const RequestFlag = ({ isActive, type, handleSelect, showFlag = true, isDisabled ); //when setting to inactive - modalHeadingActive = "OIPC Review"; + modalHeadingInactive = "OIPC Review"; modalMessageInactive = "Are you sure you want to remove the OIPC review flag from this request?"; modalDescriptionInactive = ( From 04af6c3bdccfacb30cdcb6f71f711b1df3733884 Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Wed, 27 Dec 2023 21:35:58 -0800 Subject: [PATCH 159/238] New fix for save button --- forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index add632bb2..16182bf04 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -277,7 +277,7 @@ const FOIRequest = React.memo(({ userDetail }) => { if (JSON.stringify(oipcData) != JSON.stringify(oipcDataInitial)) { setDisableInput(false) } - }, [oipcData]); + }, [oipcData, requestDetails.isoipcreview]); useEffect(() => { if (window.location.href.indexOf("comments") > -1) { From ca5cef8f5c9a49ff6f8edc89d15fc694721ea5b5 Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Wed, 27 Dec 2023 21:36:18 -0800 Subject: [PATCH 160/238] Revert changes --- .../OIPCDetails/RemoveOIPCModal.jsx | 49 +------------------ 1 file changed, 1 insertion(+), 48 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/RemoveOIPCModal.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/RemoveOIPCModal.jsx index ab1957fc2..878d8bea8 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/RemoveOIPCModal.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/RemoveOIPCModal.jsx @@ -5,11 +5,6 @@ import DialogContentText from '@material-ui/core/DialogContentText'; import DialogTitle from '@material-ui/core/DialogTitle'; import CloseIcon from '@material-ui/icons/Close'; import IconButton from '@material-ui/core/IconButton'; -import useOIPCHook from './oipcHook'; -import { deleteOIPCDetails } from '../../../../apiManager/services/FOI/foiRequestServices'; -import { useDispatch } from 'react-redux'; -import { toast } from "react-toastify"; -import { useParams } from "react-router-dom"; const RemoveOIPCModal= ({ showModal, @@ -17,52 +12,10 @@ const RemoveOIPCModal= ({ setShowModal, oipc, }) =>{ - const dispatch = useDispatch(); - const { requestId, ministryId } = useParams(); - const { setIsOIPCReview, removeAllOIPCs } = useOIPCHook(); - const saveOIPCNoReview = () => { - const toastID = toast.loading("Saving request with removed OIPC review...") - removeAllOIPCs(); - setIsOIPCReview(false); - dispatch( - deleteOIPCDetails( - requestId, - ministryId, - (err, _res) => { - if(!err) { - toast.update(toastID, { - type: "success", - render: "Removal of OIPC review has been saved successfully.", - position: "top-right", - isLoading: false, - autoClose: 3000, - hideProgressBar: true, - closeOnClick: true, - pauseOnHover: true, - draggable: true, - progress: undefined, - }); - } else { - toast.error( - "Temporarily unable to save the request with removed OIPC review. Please try again in a few minutes.", - { - position: "top-right", - autoClose: 3000, - hideProgressBar: true, - closeOnClick: true, - pauseOnHover: true, - draggable: true, - progress: undefined, - } - );} - }) - ) - } const handleSave = () => { setShowModal(false); removeOIPC(oipc.id) - saveOIPCNoReview(); }; const handleClose = () => { setShowModal(false); @@ -86,7 +39,7 @@ const RemoveOIPCModal= ({ - Are you sure you want to delete this OIPC Review? The request will be saved automatically if you continue. + Are you sure you want to delete this OIPC Review? From d05d90658e30326b49c6b95616a56dbd7425f9d0 Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Wed, 27 Dec 2023 22:03:20 -0800 Subject: [PATCH 161/238] Revert changes --- .../request_api/models/FOIMinistryRequests.py | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index 7af6981cd..a8ff5257f 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -567,20 +567,7 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us SubjectCode, SubjectCode.subjectcodeid == FOIMinistryRequestSubjectCode.subjectcodeid, isouter=True - ).filter( - or_( - FOIMinistryRequest.requeststatusid != 3, - and_( - FOIMinistryRequest.isoipcreview == True, - FOIMinistryRequest.requeststatusid == 3, - and_( - FOIMinistryRequest.foiministryrequestid == oipc_requests.foiministryrequest_id, - FOIMinistryRequest.version == oipc_requests.foiministryrequestversion_id, - oipc_requests.outcome == None - ) - ) - ) - ) + ).filter(or_(FOIMinistryRequest.requeststatusid != 3, and_(FOIMinistryRequest.isoipcreview == True, FOIMinistryRequest.requeststatusid == 3))) if(additionalfilter == 'watchingRequests'): From 43f88024cfd32226ca456bb331eb193da423df9f Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Wed, 27 Dec 2023 22:44:40 -0800 Subject: [PATCH 162/238] Remove requests with all closed OIPC reviews from queue --- .../request_api/models/FOIMinistryRequests.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index a8ff5257f..fe2b456b5 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -567,7 +567,11 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us SubjectCode, SubjectCode.subjectcodeid == FOIMinistryRequestSubjectCode.subjectcodeid, isouter=True - ).filter(or_(FOIMinistryRequest.requeststatusid != 3, and_(FOIMinistryRequest.isoipcreview == True, FOIMinistryRequest.requeststatusid == 3))) + ).join( + FOIRequestOIPC, + and_(FOIRequestOIPC.foiministryrequest_id == FOIMinistryRequest.foiministryrequestid, FOIRequestOIPC.foiministryrequestversion_id == FOIMinistryRequest.version), + isouter=True + ).filter(or_(FOIMinistryRequest.requeststatusid != 3, and_(FOIMinistryRequest.isoipcreview == True, FOIMinistryRequest.requeststatusid == 3, FOIRequestOIPC.outcomeid == None))) if(additionalfilter == 'watchingRequests'): From a1bf379215d1b4b4262b2cc67f0b9c8da9529b83 Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Wed, 27 Dec 2023 22:45:40 -0800 Subject: [PATCH 163/238] Remove unused alias --- .../request_api/models/FOIMinistryRequests.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index fe2b456b5..fd3f6947b 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -361,9 +361,6 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us #aliase for getting ministry restricted flag from FOIRestrictedMinistryRequest ministry_restricted_requests = aliased(FOIRestrictedMinistryRequest) - #alias for filtering closed OIPC requests (where outcome is selected) - oipc_requests = aliased(FOIRequestOIPC) - #filter/search if(len(filterfields) > 0 and keyword is not None): filtercondition = [] From 5bfac2e2d9392ce530971d001325937f80b03fc1 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Fri, 29 Dec 2023 15:47:13 -0800 Subject: [PATCH 164/238] duplicate bug fixed. WIP adjusting query so closed only with outcome id of none are returned for ministry and iao view in dashboard results --- .../request_api/models/FOIMinistryRequests.py | 20 ++++++++++++++----- .../request_api/models/FOIRequestOIPC.py | 2 +- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index fd3f6947b..f0fa363d9 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -354,6 +354,13 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us #subquery for getting extension count subquery_extension_count = _session.query(FOIRequestExtension.foiministryrequest_id, func.count(distinct(FOIRequestExtension.foirequestextensionid)).filter(FOIRequestExtension.isactive == True).label('extensions')).group_by(FOIRequestExtension.foiministryrequest_id).subquery() + #subquery for getting all current oipcs for foiministry request that have outcome as none (undecided outcomes) + subquery_oipc_nooutcomes = _session.query(FOIRequestOIPC.outcomeid, FOIRequestOIPC.foiministryrequest_id, FOIRequestOIPC.foiministryrequestversion_id).filter(FOIRequestOIPC.outcomeid.is_(None)).subquery() + joincondition_oipc = [ + subquery_oipc_nooutcomes.c.foiministryrequest_id == FOIMinistryRequest.foiministryrequestid, + subquery_oipc_nooutcomes.c.foiministryrequestversion_id == FOIMinistryRequest.version, + ] + #aliase for onbehalf of applicant info onbehalf_applicantmapping = aliased(FOIRequestApplicantMapping) onbehalf_applicant = aliased(FOIRequestApplicant) @@ -565,12 +572,15 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us SubjectCode.subjectcodeid == FOIMinistryRequestSubjectCode.subjectcodeid, isouter=True ).join( - FOIRequestOIPC, - and_(FOIRequestOIPC.foiministryrequest_id == FOIMinistryRequest.foiministryrequestid, FOIRequestOIPC.foiministryrequestversion_id == FOIMinistryRequest.version), + subquery_oipc_nooutcomes, + and_( + FOIMinistryRequest.isoipcreview == True, + FOIMinistryRequest.requeststatusid == 3, + *joincondition_oipc + ), isouter=True - ).filter(or_(FOIMinistryRequest.requeststatusid != 3, and_(FOIMinistryRequest.isoipcreview == True, FOIMinistryRequest.requeststatusid == 3, FOIRequestOIPC.outcomeid == None))) - - + ).filter(or_(FOIMinistryRequest.requeststatusid != 3, and_(FOIMinistryRequest.isoipcreview == True, FOIMinistryRequest.requeststatusid == 3))) + if(additionalfilter == 'watchingRequests'): #watchby activefilter = and_(FOIMinistryRequest.isactive == True, FOIRequestStatus.isactive == True) diff --git a/request-management-api/request_api/models/FOIRequestOIPC.py b/request-management-api/request_api/models/FOIRequestOIPC.py index 2931a304a..2d65c413d 100644 --- a/request-management-api/request_api/models/FOIRequestOIPC.py +++ b/request-management-api/request_api/models/FOIRequestOIPC.py @@ -58,6 +58,6 @@ def getrequestidsbyoipcno(cls, oipcno): class FOIRequestOIPCSchema(ma.Schema): class Meta: - fields = ('oipcid', 'version', 'ministryrequestid', 'investigator','ministryversion','oipcno','reviewtypeid','reasonid','statusid','outcomeid','isinquiry','inquiryattributes','isjudicialreview', + fields = ('oipcid', 'version', 'foiministryrequest_id', 'investigator', 'foiministryrequestversion_id','oipcno','reviewtypeid','reasonid','statusid','outcomeid','isinquiry','inquiryattributes','isjudicialreview', 'issubsequentappeal','receiveddate','closeddate','created_at','createdby','updated_at','updatedby', 'reviewtype.name', 'reason.name', 'status.name', 'outcome.name') \ No newline at end of file From b043dbf79ae7f5cf4b6d5face385f4b5888ad6f3 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Fri, 29 Dec 2023 15:51:34 -0800 Subject: [PATCH 165/238] Adjusted code back to original outside of dev rook. WIP removing all closed requests unless is oipc, and has outcome of none --- .../request_api/models/FOIMinistryRequests.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index f0fa363d9..bd83803e8 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -579,7 +579,7 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us *joincondition_oipc ), isouter=True - ).filter(or_(FOIMinistryRequest.requeststatusid != 3, and_(FOIMinistryRequest.isoipcreview == True, FOIMinistryRequest.requeststatusid == 3))) + ).filter(FOIMinistryRequest.requeststatusid != 3) if(additionalfilter == 'watchingRequests'): #watchby @@ -730,9 +730,7 @@ def getgroupfilters(cls, groups): or_(*groupfilter) ) - ministryfilterwithclosedoipc = or_(ministryfilter, and_(FOIMinistryRequest.isoipcreview == True, FOIMinistryRequest.requeststatusid == 3)) - - return ministryfilterwithclosedoipc + return ministryfilter @classmethod def getrequestoriginalduedate(cls,ministryrequestid): From c6e59162f876416eae4cd9ab36774d5a160ce5f4 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Fri, 29 Dec 2023 15:53:02 -0800 Subject: [PATCH 166/238] duplicate bug fixed. WIP adjusting query so closed only with outcome id of none are returned for ministry and iao view in dashboard results --- .../request_api/models/FOIMinistryRequests.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index bd83803e8..f0fa363d9 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -579,7 +579,7 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us *joincondition_oipc ), isouter=True - ).filter(FOIMinistryRequest.requeststatusid != 3) + ).filter(or_(FOIMinistryRequest.requeststatusid != 3, and_(FOIMinistryRequest.isoipcreview == True, FOIMinistryRequest.requeststatusid == 3))) if(additionalfilter == 'watchingRequests'): #watchby @@ -730,7 +730,9 @@ def getgroupfilters(cls, groups): or_(*groupfilter) ) - return ministryfilter + ministryfilterwithclosedoipc = or_(ministryfilter, and_(FOIMinistryRequest.isoipcreview == True, FOIMinistryRequest.requeststatusid == 3)) + + return ministryfilterwithclosedoipc @classmethod def getrequestoriginalduedate(cls,ministryrequestid): From 0029ae22b69a9f2b8731461efec2b6da71fe6fbe Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Tue, 2 Jan 2024 10:55:21 -0800 Subject: [PATCH 167/238] added distinct call on subquery to remove duplicates. WIP removing closed requests with no outcomes --- .../request_api/models/FOIMinistryRequests.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index f0fa363d9..6b4fe483f 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -355,7 +355,7 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us subquery_extension_count = _session.query(FOIRequestExtension.foiministryrequest_id, func.count(distinct(FOIRequestExtension.foirequestextensionid)).filter(FOIRequestExtension.isactive == True).label('extensions')).group_by(FOIRequestExtension.foiministryrequest_id).subquery() #subquery for getting all current oipcs for foiministry request that have outcome as none (undecided outcomes) - subquery_oipc_nooutcomes = _session.query(FOIRequestOIPC.outcomeid, FOIRequestOIPC.foiministryrequest_id, FOIRequestOIPC.foiministryrequestversion_id).filter(FOIRequestOIPC.outcomeid.is_(None)).subquery() + subquery_oipc_nooutcomes = _session.query(distinct(FOIRequestOIPC.foiministryrequest_id),FOIRequestOIPC.outcomeid, FOIRequestOIPC.foiministryrequest_id, FOIRequestOIPC.foiministryrequestversion_id).filter(FOIRequestOIPC.outcomeid.is_(None)).subquery() joincondition_oipc = [ subquery_oipc_nooutcomes.c.foiministryrequest_id == FOIMinistryRequest.foiministryrequestid, subquery_oipc_nooutcomes.c.foiministryrequestversion_id == FOIMinistryRequest.version, @@ -574,8 +574,6 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us ).join( subquery_oipc_nooutcomes, and_( - FOIMinistryRequest.isoipcreview == True, - FOIMinistryRequest.requeststatusid == 3, *joincondition_oipc ), isouter=True From 6c7f7fb9f98335f06985d9d78de1883ba0811729 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Tue, 2 Jan 2024 14:23:14 -0800 Subject: [PATCH 168/238] Subquery adjusted for distinct logic. WIP filteirng out outcomeid == None oipcs --- .../request_api/models/FOIMinistryRequests.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index 6b4fe483f..181acd1d1 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -355,10 +355,15 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us subquery_extension_count = _session.query(FOIRequestExtension.foiministryrequest_id, func.count(distinct(FOIRequestExtension.foirequestextensionid)).filter(FOIRequestExtension.isactive == True).label('extensions')).group_by(FOIRequestExtension.foiministryrequest_id).subquery() #subquery for getting all current oipcs for foiministry request that have outcome as none (undecided outcomes) - subquery_oipc_nooutcomes = _session.query(distinct(FOIRequestOIPC.foiministryrequest_id),FOIRequestOIPC.outcomeid, FOIRequestOIPC.foiministryrequest_id, FOIRequestOIPC.foiministryrequestversion_id).filter(FOIRequestOIPC.outcomeid.is_(None)).subquery() + subquery_oipc_nooutcomes_sql = """ + SELECT distinct on (foiministryrequest_id) foiministryrequest_id, foiministryrequestversion_id, outcomeid + FROM "FOIRequestOIPC" fo + WHERE outcomeid is null order by foiministryrequest_id, foiministryrequestversion_id desc + """ + rs_subquery_oipc_nooutcomes_sql = text(subquery_oipc_nooutcomes_sql).columns(FOIRequestOIPC.foiministryrequest_id, FOIRequestOIPC.foiministryrequestversion_id, FOIRequestOIPC.outcomeid).alias("oipcnoneoutcomes") joincondition_oipc = [ - subquery_oipc_nooutcomes.c.foiministryrequest_id == FOIMinistryRequest.foiministryrequestid, - subquery_oipc_nooutcomes.c.foiministryrequestversion_id == FOIMinistryRequest.version, + rs_subquery_oipc_nooutcomes_sql.c.foiministryrequest_id == FOIMinistryRequest.foiministryrequestid, + rs_subquery_oipc_nooutcomes_sql.c.foiministryrequestversion_id == FOIMinistryRequest.version, ] #aliase for onbehalf of applicant info @@ -572,13 +577,13 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us SubjectCode.subjectcodeid == FOIMinistryRequestSubjectCode.subjectcodeid, isouter=True ).join( - subquery_oipc_nooutcomes, + rs_subquery_oipc_nooutcomes_sql, and_( *joincondition_oipc ), isouter=True - ).filter(or_(FOIMinistryRequest.requeststatusid != 3, and_(FOIMinistryRequest.isoipcreview == True, FOIMinistryRequest.requeststatusid == 3))) - + ).filter(or_(FOIMinistryRequest.requeststatusid != 3, and_(FOIMinistryRequest.isoipcreview == True, FOIMinistryRequest.requeststatusid == 3, rs_subquery_oipc_nooutcomes_sql.c.outcomeid == None))) + if(additionalfilter == 'watchingRequests'): #watchby activefilter = and_(FOIMinistryRequest.isactive == True, FOIRequestStatus.isactive == True) From 54bd3e2cadedfbcb6f6897278b8dd10a0c8b1dd3 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Tue, 2 Jan 2024 14:53:30 -0800 Subject: [PATCH 169/238] bug fix completed. subquery implemented to gather latest foioipcrequest and then filter iout oipcs with outcome id's prsent from search dashboard. duplicate bug fixed --- .../request_api/models/FOIMinistryRequests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index 181acd1d1..980868dbb 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -358,7 +358,7 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us subquery_oipc_nooutcomes_sql = """ SELECT distinct on (foiministryrequest_id) foiministryrequest_id, foiministryrequestversion_id, outcomeid FROM "FOIRequestOIPC" fo - WHERE outcomeid is null order by foiministryrequest_id, foiministryrequestversion_id desc + order by foiministryrequest_id, foiministryrequestversion_id desc """ rs_subquery_oipc_nooutcomes_sql = text(subquery_oipc_nooutcomes_sql).columns(FOIRequestOIPC.foiministryrequest_id, FOIRequestOIPC.foiministryrequestversion_id, FOIRequestOIPC.outcomeid).alias("oipcnoneoutcomes") joincondition_oipc = [ From bb6eae88bb5cf29b186280b294701714edbfe2f7 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Tue, 2 Jan 2024 15:21:39 -0800 Subject: [PATCH 170/238] adjusted naming of subquery variable --- .../request_api/models/FOIMinistryRequests.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index 980868dbb..83e0d7655 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -354,16 +354,16 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us #subquery for getting extension count subquery_extension_count = _session.query(FOIRequestExtension.foiministryrequest_id, func.count(distinct(FOIRequestExtension.foirequestextensionid)).filter(FOIRequestExtension.isactive == True).label('extensions')).group_by(FOIRequestExtension.foiministryrequest_id).subquery() - #subquery for getting all current oipcs for foiministry request that have outcome as none (undecided outcomes) - subquery_oipc_nooutcomes_sql = """ + #subquery for getting all, distinct oipcs for foiministry request + subquery_with_oipc_sql = """ SELECT distinct on (foiministryrequest_id) foiministryrequest_id, foiministryrequestversion_id, outcomeid FROM "FOIRequestOIPC" fo order by foiministryrequest_id, foiministryrequestversion_id desc """ - rs_subquery_oipc_nooutcomes_sql = text(subquery_oipc_nooutcomes_sql).columns(FOIRequestOIPC.foiministryrequest_id, FOIRequestOIPC.foiministryrequestversion_id, FOIRequestOIPC.outcomeid).alias("oipcnoneoutcomes") + subquery_with_oipc = text(subquery_with_oipc_sql).columns(FOIRequestOIPC.foiministryrequest_id, FOIRequestOIPC.foiministryrequestversion_id, FOIRequestOIPC.outcomeid).alias("oipcnoneoutcomes") joincondition_oipc = [ - rs_subquery_oipc_nooutcomes_sql.c.foiministryrequest_id == FOIMinistryRequest.foiministryrequestid, - rs_subquery_oipc_nooutcomes_sql.c.foiministryrequestversion_id == FOIMinistryRequest.version, + subquery_with_oipc.c.foiministryrequest_id == FOIMinistryRequest.foiministryrequestid, + subquery_with_oipc.c.foiministryrequestversion_id == FOIMinistryRequest.version, ] #aliase for onbehalf of applicant info @@ -577,12 +577,12 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us SubjectCode.subjectcodeid == FOIMinistryRequestSubjectCode.subjectcodeid, isouter=True ).join( - rs_subquery_oipc_nooutcomes_sql, + subquery_with_oipc, and_( *joincondition_oipc ), isouter=True - ).filter(or_(FOIMinistryRequest.requeststatusid != 3, and_(FOIMinistryRequest.isoipcreview == True, FOIMinistryRequest.requeststatusid == 3, rs_subquery_oipc_nooutcomes_sql.c.outcomeid == None))) + ).filter(or_(FOIMinistryRequest.requeststatusid != 3, and_(FOIMinistryRequest.isoipcreview == True, FOIMinistryRequest.requeststatusid == 3, subquery_with_oipc.c.outcomeid == None))) if(additionalfilter == 'watchingRequests'): #watchby From 83c69bb1681025d020beb81032d59bdf641c90f4 Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Wed, 3 Jan 2024 12:49:04 -0800 Subject: [PATCH 171/238] Uncommented auth.require decorators --- .../request_api/resources/foiflowmasterdata.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/request-management-api/request_api/resources/foiflowmasterdata.py b/request-management-api/request_api/resources/foiflowmasterdata.py index 297880fbf..c8fe5cbde 100644 --- a/request-management-api/request_api/resources/foiflowmasterdata.py +++ b/request-management-api/request_api/resources/foiflowmasterdata.py @@ -390,7 +390,7 @@ class FOIFlowOIPCReviewTypes(Resource): @staticmethod @TRACER.trace() @cross_origin(origins=allowedorigins()) - # @auth.require + @auth.require @request_api.cache.cached( key_prefix="oipcreviewtypesreasons", unless=cache_filter, @@ -412,7 +412,7 @@ class FOIFlowOIPCStatuses(Resource): @staticmethod @TRACER.trace() @cross_origin(origins=allowedorigins()) - # @auth.require + @auth.require @request_api.cache.cached( key_prefix="oipcstatuses", unless=cache_filter, @@ -435,7 +435,7 @@ class FOIFlowOIPCOutcomes(Resource): @staticmethod @TRACER.trace() @cross_origin(origins=allowedorigins()) - # @auth.require + @auth.require @request_api.cache.cached( key_prefix="oipcoutcomes", unless=cache_filter, @@ -457,7 +457,7 @@ class FOIFlowOIPCInquiryOutcomes(Resource): @staticmethod @TRACER.trace() @cross_origin(origins=allowedorigins()) - # @auth.require + @auth.require @request_api.cache.cached( key_prefix="oipcinquiryoutcomes", unless=cache_filter, From fa51cddab2d9259c35e2f3ba77be148f3014887f Mon Sep 17 00:00:00 2001 From: divyav-aot <79858022+divyav-aot@users.noreply.github.com> Date: Thu, 4 Jan 2024 12:43:20 -0500 Subject: [PATCH 172/238] Update FOIMinistryRequests.py Added a print statement to check the data --- request-management-api/request_api/models/FOIMinistryRequests.py | 1 + 1 file changed, 1 insertion(+) diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index 2793447b6..08ff64c34 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -744,6 +744,7 @@ def getupcominglegislativeduerecords(cls): order by filenumber , version desc;""" requeststatuslabel = [StateName.closed.name,StateName.redirect.name,StateName.unopened.name,StateName.intakeinprogress.name,StateName.onhold.name,StateName.archived.name] requeststatuslabel = ','.join(str(e) for e in requeststatuslabel) + print(f"requeststatuslabel ====== {requeststatuslabel}") rs = db.session.execute(text(sql), {'requeststatuslabel': requeststatuslabel}) for row in rs: upcomingduerecords.append({"filenumber": row["filenumber"], "duedate": row["duedate"],"foiministryrequestid": row["foiministryrequestid"], "version": row["version"], "foirequest_id": row["foirequest_id"], "created_at": row["created_at"], "createdby": row["createdby"]}) From 546ceaba2dfacdff3b2fd6e6ff69857a72219151 Mon Sep 17 00:00:00 2001 From: divyav-aot Date: Thu, 4 Jan 2024 13:09:24 -0500 Subject: [PATCH 173/238] query fixed --- .../request_api/models/FOIMinistryRequests.py | 10 ++++------ .../request_api/models/FOIRequestNotifications.py | 10 +++++----- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index 2793447b6..4db017a84 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -739,11 +739,10 @@ def getupcominglegislativeduerecords(cls): upcomingduerecords = [] try: sql = """select distinct on (filenumber) filenumber, to_char(duedate, 'YYYY-MM-DD') as duedate, foiministryrequestid, version, foirequest_id, created_at, createdby from "FOIMinistryRequests" fpa - where isactive = true and duedate is not null and requeststatuslabel not in (:requeststatuslabel) + where isactive = true and duedate is not null and requeststatuslabel not in :requeststatuslabel and duedate between NOW() - INTERVAL '7 DAY' AND NOW() + INTERVAL '7 DAY' order by filenumber , version desc;""" - requeststatuslabel = [StateName.closed.name,StateName.redirect.name,StateName.unopened.name,StateName.intakeinprogress.name,StateName.onhold.name,StateName.archived.name] - requeststatuslabel = ','.join(str(e) for e in requeststatuslabel) + requeststatuslabel = tuple([StateName.closed.name,StateName.redirect.name,StateName.unopened.name,StateName.intakeinprogress.name,StateName.onhold.name,StateName.archived.name]) rs = db.session.execute(text(sql), {'requeststatuslabel': requeststatuslabel}) for row in rs: upcomingduerecords.append({"filenumber": row["filenumber"], "duedate": row["duedate"],"foiministryrequestid": row["foiministryrequestid"], "version": row["version"], "foirequest_id": row["foirequest_id"], "created_at": row["created_at"], "createdby": row["createdby"]}) @@ -764,13 +763,12 @@ def getupcomingdivisionduerecords(cls): from "FOIMinistryRequestDivisions" frd inner join (select distinct on (fpa.foiministryrequestid) foiministryrequestid, version as foiministryrequestversion, axisrequestid, filenumber, foirequest_id, requeststatusid, requeststatuslabel from "FOIMinistryRequests" fpa - order by fpa.foiministryrequestid , fpa.version desc) fma on frd.foiministryrequest_id = fma.foiministryrequestid and frd.foiministryrequestversion_id = fma.foiministryrequestversion and fma.requeststatuslabel not in (:requeststatuslabel) + order by fpa.foiministryrequestid , fpa.version desc) fma on frd.foiministryrequest_id = fma.foiministryrequestid and frd.foiministryrequestversion_id = fma.foiministryrequestversion and fma.requeststatuslabel not in :requeststatuslabel inner join "ProgramAreaDivisions" pad2 on frd.divisionid = pad2.divisionid inner join "ProgramAreaDivisionStages" pads on frd.stageid = pads.stageid and frd.stageid in (5, 7, 9) and frd.divisionduedate between NOW() - INTERVAL '7 DAY' AND NOW() + INTERVAL '7 DAY' order by frd.foiministryrequest_id , frd.foiministryrequestversion_id desc;""" - requeststatuslabel = [StateName.closed.name,StateName.redirect.name,StateName.unopened.name,StateName.intakeinprogress.name,StateName.onhold.name,StateName.archived.name] - requeststatuslabel = ','.join(str(e) for e in requeststatuslabel) + requeststatuslabel = tuple([StateName.closed.name,StateName.redirect.name,StateName.unopened.name,StateName.intakeinprogress.name,StateName.onhold.name,StateName.archived.name]) rs = db.session.execute(text(sql), {'requeststatuslabel': requeststatuslabel}) for row in rs: diff --git a/request-management-api/request_api/models/FOIRequestNotifications.py b/request-management-api/request_api/models/FOIRequestNotifications.py index c48483388..1d8a061d2 100644 --- a/request-management-api/request_api/models/FOIRequestNotifications.py +++ b/request-management-api/request_api/models/FOIRequestNotifications.py @@ -89,15 +89,15 @@ def getcommentnotifications(cls, commentid): notifications = [] try: sql = """select idnumber, axisnumber, notificationid, notificationuserid, notification , notificationtype, userid, notificationusertype, created_at, createdby, requesttype, requestid, foirequestid from ( - select frn.idnumber, frn.axisnumber, frn.requestid, frn.notificationid, frns.notificationuserid, frn.notification -> 'message' as notification , nty.name as notificationtype, frn.created_at , frns.createdby, frns.userid, ntu.name as notificationusertype, 'ministryrequest' requesttype, frn.foirequestid from "FOIRequestNotifications" frn inner join "FOIRequestNotificationUsers" frns on frn.notificationid = frns.notificationid and frns.isdeleted = false inner join "NotificationTypes" nty on frn.notificationtypelabel = nty.notificationtypelabel inner join "NotificationUserTypes" ntu on frns.notificationusertypelabel = ntu.notificationusertypelabel where frn.notificationtypelabel in (:notificationtypelabel) and (frn.notification ->> 'commentid')::int = :commentid + select frn.idnumber, frn.axisnumber, frn.requestid, frn.notificationid, frns.notificationuserid, frn.notification -> 'message' as notification , nty.name as notificationtype, frn.created_at , frns.createdby, frns.userid, ntu.name as notificationusertype, 'ministryrequest' requesttype, frn.foirequestid from "FOIRequestNotifications" frn inner join "FOIRequestNotificationUsers" frns on frn.notificationid = frns.notificationid and frns.isdeleted = false inner join "NotificationTypes" nty on frn.notificationtypelabel = nty.notificationtypelabel inner join "NotificationUserTypes" ntu on frns.notificationusertypelabel = ntu.notificationusertypelabel where frn.notificationtypelabel in :notificationtypelabel and (frn.notification ->> 'commentid')::int = :commentid union all - select frn.idnumber, frn.axisnumber, frn.requestid, frn.notificationid, frns.notificationuserid, frn.notification -> 'message' as notification, nty.name as notificationtype, frn.created_at , frns.createdby, frns.userid, ntu.name as notificationusertype, 'rawrequest' requesttype, 0 foirequestid from "FOIRawRequestNotifications" frn inner join "FOIRawRequestNotificationUsers" frns on frn.notificationid = frns.notificationid and frns.isdeleted = false inner join "NotificationTypes" nty on frn.notificationtypelabel = nty.notificationtypelabel inner join "NotificationUserTypes" ntu on frns.notificationusertypelabel = ntu.notificationusertypelabel where frn.notificationtypelabel in (:notificationtypelabel) and (frn.notification ->> 'commentid')::int = :commentid + select frn.idnumber, frn.axisnumber, frn.requestid, frn.notificationid, frns.notificationuserid, frn.notification -> 'message' as notification, nty.name as notificationtype, frn.created_at , frns.createdby, frns.userid, ntu.name as notificationusertype, 'rawrequest' requesttype, 0 foirequestid from "FOIRawRequestNotifications" frn inner join "FOIRawRequestNotificationUsers" frns on frn.notificationid = frns.notificationid and frns.isdeleted = false inner join "NotificationTypes" nty on frn.notificationtypelabel = nty.notificationtypelabel inner join "NotificationUserTypes" ntu on frns.notificationusertypelabel = ntu.notificationusertypelabel where frn.notificationtypelabel in :notificationtypelabel and (frn.notification ->> 'commentid')::int = :commentid ) as notf order by created_at desc""" - notificationtypelabel = [notificationtypes_cache['newusercomments']['notificationtypelabel'], + notificationtypelabel = tuple([notificationtypes_cache['newusercomments']['notificationtypelabel'], notificationtypes_cache['replyusercomments']['notificationtypelabel'], notificationtypes_cache['taggedusercomments']['notificationtypelabel'], - ] # 3,9,10 - notificationtypelabel = ','.join(str(e) for e in notificationtypelabel) + ]) # 3,9,10 + # notificationtypelabel = ','.join(str(e) for e in notificationtypelabel) rs = db.session.execute(text(sql), {'commentid': commentid, 'notificationtypelabel': notificationtypelabel}) for row in rs: dt = maya.parse(row["created_at"]).datetime(to_timezone='America/Vancouver', naive=False) From f4f6995c3901bba9dced06505a79715b8909d20f Mon Sep 17 00:00:00 2001 From: Aman-Hundal Date: Thu, 4 Jan 2024 13:44:01 -0800 Subject: [PATCH 174/238] Adjusted backend pdfpackage data to send over additional field for readable datetime field + adjusted frontend to show this time via a tooltop to FE users --- .../FOI/customComponents/Records/index.js | 14 +++++++++++++- .../request_api/services/recordservice.py | 3 +++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/forms-flow-web/src/components/FOI/customComponents/Records/index.js b/forms-flow-web/src/components/FOI/customComponents/Records/index.js index 85373fdac..e54b1fbba 100644 --- a/forms-flow-web/src/components/FOI/customComponents/Records/index.js +++ b/forms-flow-web/src/components/FOI/customComponents/Records/index.js @@ -1092,6 +1092,16 @@ export const RecordsLog = ({ (itemid === 5 && isOIPCRedlineReviewInProgress) ); }; + + const getPackageDatetime = (itemid) => { + return ( + (itemid === 1 && pdfStitchedRecord?.createdat_datetime) || + (itemid === 2 && redlinePdfStitchedRecord?.createdat_datetime) || + (itemid === 3 && responsePackagePdfStitchedRecord?.createdat_datetime) || + (itemid === 4 && oipcRedlinePdfStitchedRecord?.createdat_datetime) || + (itemid === 5 && oipcRedlineReviewPdfStitchedRecord?.createdat_datetime) + ); + } const downloadAllDocuments = async () => { let blobs = []; @@ -1720,7 +1730,9 @@ export const RecordsLog = ({ className={classes.statusIcons} /> ) : null} - {item.label} + + {item.label} + ); } diff --git a/request-management-api/request_api/services/recordservice.py b/request-management-api/request_api/services/recordservice.py index eda12999a..b27d49039 100644 --- a/request-management-api/request_api/services/recordservice.py +++ b/request-management-api/request_api/services/recordservice.py @@ -181,6 +181,9 @@ def triggerpdfstitchservice(self, requestid, ministryrequestid, recordschema, us def getpdfstitchpackagetodownload(self, ministryid, category): response, err = self.makedocreviewerrequest('GET', '/api/pdfstitch/{0}/{1}'.format(ministryid, category)) + if response is not None and "createdat" in response: + string_datetime = maya.parse(response["createdat"]).datetime(to_timezone='America/Vancouver', naive=False).strftime('%Y %b %d | %I:%M %p').upper() + response["createdat_datetime"] = string_datetime return response def getpdfstichstatus(self, ministryid, category): From 47ae0f711acfe42cc81635ea78cff7cfdcf4ec00 Mon Sep 17 00:00:00 2001 From: divyav-aot Date: Thu, 4 Jan 2024 17:13:26 -0500 Subject: [PATCH 175/238] debug statements --- .../request_api/services/eventservice.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/request-management-api/request_api/services/eventservice.py b/request-management-api/request_api/services/eventservice.py index 9610cb5a6..2b408a012 100644 --- a/request-management-api/request_api/services/eventservice.py +++ b/request-management-api/request_api/services/eventservice.py @@ -57,11 +57,16 @@ def posteventforaxisextension(self, ministryrequestid, extensionids, userid, use def postreminderevent(self): try: - cfreventresponse = cfrdateevent().createdueevent() - legislativeeventresponse = legislativedateevent().createdueevent() - divisioneventresponse = divisiondateevent().createdueevent() + cfreventresponse = cfrdateevent().createdueevent() + print(f"cfreventresponse = {cfreventresponse.success}") + legislativeeventresponse = legislativedateevent().createdueevent() + print(f"legislativeeventresponse = {legislativeeventresponse.success}") + divisioneventresponse = divisiondateevent().createdueevent() + print(f"divisioneventresponse = {divisioneventresponse.success}") paymentremindereventresponse = paymentevent().createpaymentreminderevent() + print(f"paymentremindereventresponse = {paymentremindereventresponse.success}") section5pendingresponse = section5pendingevent().createdueevent() + print(f"section5pendingresponse = {section5pendingresponse.success}") if cfreventresponse.success == False or legislativeeventresponse.success == False or divisioneventresponse.success == False or paymentremindereventresponse.success == False or section5pendingresponse == False: current_app.logger.error("FOI Notification failed for reminder event response=%s ; legislative response=%s ; division response=%s ; payment response=%s ; section5pending response=%s" % (cfreventresponse.message, legislativeeventresponse.message, divisioneventresponse.message, paymentremindereventresponse.message, section5pendingresponse.message)) return DefaultMethodResult(False,'Due reminder notifications failed',cfreventresponse.identifier) From 76f2b4c0e835bf89b9a3d6a7b7c9538a4feb8325 Mon Sep 17 00:00:00 2001 From: Shivakumar Date: Thu, 4 Jan 2024 14:29:34 -0800 Subject: [PATCH 176/238] Added debug meesage for post reminder event --- .../request_api/services/eventservice.py | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/request-management-api/request_api/services/eventservice.py b/request-management-api/request_api/services/eventservice.py index 9610cb5a6..29e803cb2 100644 --- a/request-management-api/request_api/services/eventservice.py +++ b/request-management-api/request_api/services/eventservice.py @@ -17,6 +17,7 @@ from request_api.models.default_method_result import DefaultMethodResult from request_api.exceptions import BusinessException from request_api.utils.enums import PaymentEventType +import time as timer import json from flask import current_app @@ -57,11 +58,32 @@ def posteventforaxisextension(self, ministryrequestid, extensionids, userid, use def postreminderevent(self): try: - cfreventresponse = cfrdateevent().createdueevent() - legislativeeventresponse = legislativedateevent().createdueevent() - divisioneventresponse = divisiondateevent().createdueevent() + start_time = timer.time() + cfreventresponse = cfrdateevent().createdueevent() + cfreventresponse_time = timer.time() + print("--- CFR Event Response Time %s seconds ---" % (cfreventresponse_time - start_time)) + print(f"cfreventresponse = {cfreventresponse.success}") + + legislativeeventresponse = legislativedateevent().createdueevent() + legislativeeventresponse_time = timer.time() + print("--- Legislative Event Response Time %s seconds ---" % (legislativeeventresponse_time - cfreventresponse_time)) + print(f"legislativeeventresponse = {legislativeeventresponse.success}") + + divisioneventresponse = divisiondateevent().createdueevent() + divisioneventresponse_time = timer.time() + print("--- Division Event Response Time %s seconds ---" % (divisioneventresponse_time - legislativeeventresponse_time)) + print(f"divisioneventresponse = {divisioneventresponse.success}") + paymentremindereventresponse = paymentevent().createpaymentreminderevent() + paymentremindereventresponse_time = timer.time() + print("--- Payment Reminder Event Response Time %s seconds ---" % (paymentremindereventresponse_time - divisioneventresponse_time)) + print(f"paymentremindereventresponse = {paymentremindereventresponse.success}") + section5pendingresponse = section5pendingevent().createdueevent() + section5pendingresponse_time = timer.time() + print("--- Section 5 Pending Event Response Time %s seconds ---" % (section5pendingresponse_time - paymentremindereventresponse_time)) + print(f"section5pendingresponse = {section5pendingresponse.success}") + if cfreventresponse.success == False or legislativeeventresponse.success == False or divisioneventresponse.success == False or paymentremindereventresponse.success == False or section5pendingresponse == False: current_app.logger.error("FOI Notification failed for reminder event response=%s ; legislative response=%s ; division response=%s ; payment response=%s ; section5pending response=%s" % (cfreventresponse.message, legislativeeventresponse.message, divisioneventresponse.message, paymentremindereventresponse.message, section5pendingresponse.message)) return DefaultMethodResult(False,'Due reminder notifications failed',cfreventresponse.identifier) From 075c2665e8f126e4c3948bae98511bebda7f507e Mon Sep 17 00:00:00 2001 From: "sumathi.thirumani" Date: Thu, 4 Jan 2024 14:36:46 -0800 Subject: [PATCH 177/238] Release of 4953 --- .../components/FOI/FOIRequest/FOIRequest.js | 6 ++--- .../FOI/FOIRequest/RedactionSummary.js | 22 ++++++++++++++----- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index 16182bf04..1374d91da 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -310,7 +310,8 @@ const FOIRequest = React.memo(({ userDetail }) => { dispatch(fetchApplicantCorrespondenceTemplates()); dispatch( fetchRedactedSections(ministryId, (_err, res) => { - setRedactedSections(res.sections); + setRedactedSections(res); + }) ); } @@ -1294,8 +1295,7 @@ const FOIRequest = React.memo(({ userDetail }) => { createSaveRequestObject={createSaveRequestObject} disableInput={disableInput} /> - - {redactedSections.length > 0 && ( + {Object.keys(redactedSections).length > 0 && ( )} diff --git a/forms-flow-web/src/components/FOI/FOIRequest/RedactionSummary.js b/forms-flow-web/src/components/FOI/FOIRequest/RedactionSummary.js index 2aa8d67f4..9d1d08a52 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/RedactionSummary.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/RedactionSummary.js @@ -9,8 +9,7 @@ import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; const RedactionSummary = React.memo(({sections}) => { - - const useStyles = makeStyles({ + const useStyles = makeStyles({ heading: { color: '#FFF', fontSize: '16px !important', @@ -34,12 +33,25 @@ const RedactionSummary = React.memo(({sections}) => { SUMMARY OF REDACTIONS -
+ + + {sections?.Redline !== "" && ( +
Redaction Sections Applied - {sections} -
+ {sections?.Redline} +
+ )} + {(sections.OIPC && sections?.OIPC !== "") && ( +
+ + OIPC Redaction Sections Applied + + {sections?.OIPC} +
+ )} +
From 43bc1739a9956a322b57bfba42e51ef41a2d2f2e Mon Sep 17 00:00:00 2001 From: Shivakumar Date: Thu, 4 Jan 2024 14:29:34 -0800 Subject: [PATCH 178/238] Added debug meesage for post reminder event --- request-management-api/request_api/services/eventservice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/request-management-api/request_api/services/eventservice.py b/request-management-api/request_api/services/eventservice.py index 29e803cb2..4f22536b5 100644 --- a/request-management-api/request_api/services/eventservice.py +++ b/request-management-api/request_api/services/eventservice.py @@ -83,7 +83,7 @@ def postreminderevent(self): section5pendingresponse_time = timer.time() print("--- Section 5 Pending Event Response Time %s seconds ---" % (section5pendingresponse_time - paymentremindereventresponse_time)) print(f"section5pendingresponse = {section5pendingresponse.success}") - + if cfreventresponse.success == False or legislativeeventresponse.success == False or divisioneventresponse.success == False or paymentremindereventresponse.success == False or section5pendingresponse == False: current_app.logger.error("FOI Notification failed for reminder event response=%s ; legislative response=%s ; division response=%s ; payment response=%s ; section5pending response=%s" % (cfreventresponse.message, legislativeeventresponse.message, divisioneventresponse.message, paymentremindereventresponse.message, section5pendingresponse.message)) return DefaultMethodResult(False,'Due reminder notifications failed',cfreventresponse.identifier) From 0eef0f951a580f079a17c38c2a9c2b67669ab113 Mon Sep 17 00:00:00 2001 From: divyav-aot Date: Thu, 4 Jan 2024 18:22:53 -0500 Subject: [PATCH 179/238] added isdeleted=false --- .../request_api/models/FOIRawRequestNotifications.py | 2 +- .../request_api/models/FOIRequestNotifications.py | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/request-management-api/request_api/models/FOIRawRequestNotifications.py b/request-management-api/request_api/models/FOIRawRequestNotifications.py index 4104b90ec..7cbf8cef9 100644 --- a/request-management-api/request_api/models/FOIRawRequestNotifications.py +++ b/request-management-api/request_api/models/FOIRawRequestNotifications.py @@ -102,7 +102,7 @@ def getnotificationidsbynumber(cls, idnumber): def getnotificationidsbytype(cls, notificationtypelabel): notificationids = [] try: - sql = """select notificationid from "FOIRawRequestNotifications" where notificationtypelabel= :notificationtypelabel """ + sql = """select notificationid from "FOIRawRequestNotifications" where notificationtypelabel= :notificationtypelabel and isdeleted = false """ rs = db.session.execute(text(sql), {'notificationtypelabel': notificationtypelabel}) for row in rs: notificationids.append(row["notificationid"]) diff --git a/request-management-api/request_api/models/FOIRequestNotifications.py b/request-management-api/request_api/models/FOIRequestNotifications.py index 1d8a061d2..fc8728878 100644 --- a/request-management-api/request_api/models/FOIRequestNotifications.py +++ b/request-management-api/request_api/models/FOIRequestNotifications.py @@ -114,7 +114,7 @@ def getcommentnotifications(cls, commentid): def getextensionnotifications(cls, extensionid): notifications = [] try: - sql = sql = """select idnumber, axisnumber, notificationid, notification , notificationtypelabel from "FOIRequestNotifications" where notification->>'extensionid' = :extensionid """ + sql = sql = """select idnumber, axisnumber, notificationid, notification , notificationtypelabel from "FOIRequestNotifications" where isdeleted = false and notification->>'extensionid' = :extensionid """ rs = db.session.execute(text(sql), {'extensionid': str(extensionid)}) for row in rs: notifications.append({"idnumber": row["idnumber"], "axisnumber": row["axisnumber"], "notificationid": row["notificationid"], "notification": row["notification"], "notificationtypelabel": row["notificationtypelabel"]}) @@ -140,7 +140,7 @@ def dismissnotification(cls, notificationids, userid='system'): def getnotificationidsbynumberandtype(cls, idnumber, notificationtypelabels): notificationids = [] try: - sql = """select notificationid from "FOIRequestNotifications" where idnumber = :idnumber and notificationtypelabel = ANY(:notificationtypelabels) """ + sql = """select notificationid from "FOIRequestNotifications" where idnumber = :idnumber and notificationtypelabel = ANY(:notificationtypelabels) and isdeleted = false """ rs = db.session.execute(text(sql), {'idnumber': idnumber, 'notificationtypelabels': notificationtypelabels}) for row in rs: notificationids.append(row["notificationid"]) @@ -155,7 +155,7 @@ def getnotificationidsbynumberandtype(cls, idnumber, notificationtypelabels): def getnotificationidsbynumber(cls, idnumber): notificationids = [] try: - sql = """select notificationid from "FOIRequestNotifications" where idnumber = :idnumber """ + sql = """select notificationid from "FOIRequestNotifications" where idnumber = :idnumber and isdeleted = false """ rs = db.session.execute(text(sql), {'idnumber': idnumber}) for row in rs: notificationids.append(row["notificationid"]) @@ -168,7 +168,7 @@ def getnotificationidsbynumber(cls, idnumber): @classmethod def getnotificationidsbytype(cls, notificationtypelabel): - sql = """select notificationid from "FOIRequestNotifications" where notificationtypelabel= :notificationtypelabel """ + sql = """select notificationid from "FOIRequestNotifications" where notificationtypelabel= :notificationtypelabel and isdeleted = false """ rs = db.session.execute(text(sql), {'notificationtypelabel': notificationtypelabel}) notificationids = [] for row in rs: @@ -177,7 +177,7 @@ def getnotificationidsbytype(cls, notificationtypelabel): @classmethod def getextensionnotificationidsbyministry(cls, ministryid): - sql = """select notificationid from "FOIRequestNotifications" where requestid = :requestid and notificationtypelabel = 4 """ + sql = """select notificationid from "FOIRequestNotifications" where requestid = :requestid and notificationtypelabel = 4 and isdeleted = false """ rs = db.session.execute(text(sql), {'requestid': ministryid}) notificationids = [] for row in rs: From e1280940ce1095f1f5ee3e8351846decc8f9826b Mon Sep 17 00:00:00 2001 From: Shivakumar Date: Thu, 4 Jan 2024 15:56:17 -0800 Subject: [PATCH 180/238] Added more logs --- .../request_api/services/events/cfrdate.py | 10 +++++++++- .../request_api/services/events/legislativedate.py | 7 +++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/request-management-api/request_api/services/events/cfrdate.py b/request-management-api/request_api/services/events/cfrdate.py index 7f353b710..381287dd8 100644 --- a/request-management-api/request_api/services/events/cfrdate.py +++ b/request-management-api/request_api/services/events/cfrdate.py @@ -16,6 +16,7 @@ import os from flask import current_app from dateutil.parser import parse +import time as t class cfrdateevent(duecalculator): """ FOI Event management service @@ -24,7 +25,11 @@ class cfrdateevent(duecalculator): def createdueevent(self): try: _today = self.gettoday() - notificationservice().dismissremindernotification("ministryrequest", self.__notificationtype()) + time = t.time() + notificationservice().dismissremindernotification("ministryrequest", self.__notificationtype()) + dismissremindernotification_time = t.time() + print("dismissremindernotification_time: %s" % (dismissremindernotification_time - time)) + ca_holidays = self.getholidays() _upcomingdues = FOIMinistryRequest.getupcomingcfrduerecords() for entry in _upcomingdues: @@ -34,8 +39,11 @@ def createdueevent(self): message = self.__todayduemessage() elif self.getpreviousbusinessday(entry['cfrduedate'],ca_holidays) == _today: message = self.__upcomingduemessage(_duedate) + createnotification_time = t.time() self.__createnotification(message,entry['foiministryrequestid']) self.__createcomment(entry, message) + createnotification_time = t.time() - createnotification_time + print("createnotification_time: %s" % createnotification_time) return DefaultMethodResult(True,'CFR reminder notifications created',_today) except BusinessException as exception: current_app.logger.error("%s,%s" % ('CFR reminder Notification Error', exception.message)) diff --git a/request-management-api/request_api/services/events/legislativedate.py b/request-management-api/request_api/services/events/legislativedate.py index 41ab4669f..c459a1c7b 100644 --- a/request-management-api/request_api/services/events/legislativedate.py +++ b/request-management-api/request_api/services/events/legislativedate.py @@ -16,6 +16,7 @@ import os from flask import current_app from dateutil.parser import parse +import time as t class legislativedateevent(duecalculator): """ FOI Event management service @@ -35,8 +36,14 @@ def createdueevent(self): message = self.__todayduemessage() elif self.getpreviousbusinessday(entry['duedate'],ca_holidays) == _today or self.getbusinessdaysbetween(entry['duedate'],_today) == 5: message = self.__upcomingduemessage(_duedate) + createnotification_time = t.time() self.__createnotification(message,entry['foiministryrequestid']) + createnotification_time = t.time() - createnotification_time + print("createnotification_time: %s" % createnotification_time) + createcomment_time = t.time() self.__createcomment(entry, message) + createcomment_time = t.time() - createcomment_time + print("createcomment_time: %s" % createcomment_time) return DefaultMethodResult(True,'Legislative reminder notifications created',_today) except BusinessException as exception: current_app.logger.error("%s,%s" % ('Legislative reminder Notification Error', exception.message)) From e42b168e9588559858f8b2161738de99b90260a2 Mon Sep 17 00:00:00 2001 From: Shivakumar Date: Thu, 4 Jan 2024 16:06:33 -0800 Subject: [PATCH 181/238] Added more logs --- request-management-api/request_api/services/events/cfrdate.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/request-management-api/request_api/services/events/cfrdate.py b/request-management-api/request_api/services/events/cfrdate.py index 381287dd8..82f5a9182 100644 --- a/request-management-api/request_api/services/events/cfrdate.py +++ b/request-management-api/request_api/services/events/cfrdate.py @@ -31,7 +31,11 @@ def createdueevent(self): print("dismissremindernotification_time: %s" % (dismissremindernotification_time - time)) ca_holidays = self.getholidays() + time = t.time() _upcomingdues = FOIMinistryRequest.getupcomingcfrduerecords() + getupcomingcfrduerecords_time = t.time() + print("getupcomingcfrduerecords_time: %s" % (getupcomingcfrduerecords_time - time)) + for entry in _upcomingdues: _duedate = self.formatduedate(entry['cfrduedate']) message = None From 0f780aaefd72740fb9a724e0f45b58eac90b2fbf Mon Sep 17 00:00:00 2001 From: "sumathi.thirumani" Date: Thu, 4 Jan 2024 16:22:25 -0800 Subject: [PATCH 182/238] Changes to not show oipc redaction summary if flag is turned off. --- forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js | 2 +- .../src/components/FOI/FOIRequest/RedactionSummary.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index 1374d91da..b47304abb 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -1296,7 +1296,7 @@ const FOIRequest = React.memo(({ userDetail }) => { disableInput={disableInput} /> {Object.keys(redactedSections).length > 0 && ( - + )} { +const RedactionSummary = React.memo(({sections, isoipcreview}) => { const useStyles = makeStyles({ heading: { color: '#FFF', @@ -43,7 +43,7 @@ const RedactionSummary = React.memo(({sections}) => { {sections?.Redline}
)} - {(sections.OIPC && sections?.OIPC !== "") && ( + {(isoipcreview && sections.OIPC && sections?.OIPC !== "") && (
OIPC Redaction Sections Applied From 9274c3d22d40f04ac308af67f949ffc6777379ee Mon Sep 17 00:00:00 2001 From: Shivakumar Date: Thu, 4 Jan 2024 16:52:54 -0800 Subject: [PATCH 183/238] Added more logs --- .../request_api/services/notificationservice.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/request-management-api/request_api/services/notificationservice.py b/request-management-api/request_api/services/notificationservice.py index 4b31c3e5d..00c968cd6 100644 --- a/request-management-api/request_api/services/notificationservice.py +++ b/request-management-api/request_api/services/notificationservice.py @@ -25,6 +25,9 @@ from request_api.services.external.keycloakadminservice import KeycloakAdminService from request_api.models.OperatingTeams import OperatingTeam import logging +file = open('common/notificationtypes.json', encoding="utf8") +notificationtypes_cache = json.load(file) + class notificationservice: """ FOI notification management service @@ -273,8 +276,16 @@ def __preparenotification(self, message, requesttype, notificationtype, userid, notification.idnumber ='U-00' + str(foirequest['requestid']) mutenotification = False - notification.notificationtypelabel = notificationconfig().getnotificationtypelabel(notificationtype) - notification.notificationtypeid = notificationconfig().getnotificationtypeid(notificationtype) + print("notificationtype", notificationtype) + notificationtypes_data = notificationtypes_cache[notificationtype] + if notificationtypes_data is None: + print('Notification type not found', notificationtype) + notification.notificationtypelabel = notificationconfig().getnotificationtypelabel(notificationtype) + notification.notificationtypeid = notificationconfig().getnotificationtypeid(notificationtype) + else: + print('Notification type found', notificationtype) + notification.notificationtypelabel = notificationtypes_data['notificationtypelabel'] + notification.notificationtypeid = notificationtypes_data['notificationtypeid'] notification.axisnumber = foirequest["axisrequestid"] notification.version = foirequest["version"] notification.createdby = userid From 6ab5bc1ffea1d45732069f444b15c72c8398daf5 Mon Sep 17 00:00:00 2001 From: Shivakumar Date: Fri, 5 Jan 2024 08:52:53 -0800 Subject: [PATCH 184/238] Fetch data from enum not from the database --- .../request_api/services/notificationservice.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/request-management-api/request_api/services/notificationservice.py b/request-management-api/request_api/services/notificationservice.py index 00c968cd6..f3a873c7d 100644 --- a/request-management-api/request_api/services/notificationservice.py +++ b/request-management-api/request_api/services/notificationservice.py @@ -277,15 +277,15 @@ def __preparenotification(self, message, requesttype, notificationtype, userid, mutenotification = False print("notificationtype", notificationtype) - notificationtypes_data = notificationtypes_cache[notificationtype] - if notificationtypes_data is None: - print('Notification type not found', notificationtype) - notification.notificationtypelabel = notificationconfig().getnotificationtypelabel(notificationtype) - notification.notificationtypeid = notificationconfig().getnotificationtypeid(notificationtype) + # in notificationtype remove space and make lower case + notificationtype_format = notificationtype.replace(" ", "").lower() + print ("notificationtype_format", notificationtype_format) + if notificationtype_format not in notificationtypes_cache: + print('Notification type not found in enum.', notificationtype) else: print('Notification type found', notificationtype) - notification.notificationtypelabel = notificationtypes_data['notificationtypelabel'] - notification.notificationtypeid = notificationtypes_data['notificationtypeid'] + notification.notificationtypelabel = notificationtypes_cache[notificationtype_format]['notificationtypelabel'] + notification.notificationtypeid = notificationtypes_cache[notificationtype_format]['notificationtypeid'] notification.axisnumber = foirequest["axisrequestid"] notification.version = foirequest["version"] notification.createdby = userid From 8f478ad9d55502691bd59ce05d46c4d9025b8000 Mon Sep 17 00:00:00 2001 From: divyav-aot Date: Fri, 5 Jan 2024 12:01:15 -0500 Subject: [PATCH 185/238] query updated --- .../request_api/models/FOIRawRequestNotificationUsers.py | 2 +- .../request_api/models/FOIRawRequestNotifications.py | 2 +- .../request_api/models/FOIRequestNotificationUsers.py | 2 +- .../request_api/models/FOIRequestNotifications.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/request-management-api/request_api/models/FOIRawRequestNotificationUsers.py b/request-management-api/request_api/models/FOIRawRequestNotificationUsers.py index f8d879de2..2f114310d 100644 --- a/request-management-api/request_api/models/FOIRawRequestNotificationUsers.py +++ b/request-management-api/request_api/models/FOIRawRequestNotificationUsers.py @@ -116,7 +116,7 @@ def getnotificationsbyuserandtype(cls, userid, typeid): @classmethod def dismissbynotificationid(cls, notificationids, userid='system'): - db.session.query(FOIRawRequestNotificationUser).filter(FOIRawRequestNotificationUser.notificationid.in_(notificationids)).update({FOIRawRequestNotificationUser.isdeleted: True, FOIRawRequestNotificationUser.updatedby: userid, + db.session.query(FOIRawRequestNotificationUser).filter(FOIRawRequestNotificationUser.notificationid.in_(notificationids), FOIRawRequestNotificationUser.isdeleted == False).update({FOIRawRequestNotificationUser.isdeleted: True, FOIRawRequestNotificationUser.updatedby: userid, FOIRawRequestNotificationUser.updated_at: datetime2.now()}, synchronize_session=False) db.session.commit() return DefaultMethodResult(True,'Notifications deleted for id',notificationids) diff --git a/request-management-api/request_api/models/FOIRawRequestNotifications.py b/request-management-api/request_api/models/FOIRawRequestNotifications.py index 7cbf8cef9..d95a1fac4 100644 --- a/request-management-api/request_api/models/FOIRawRequestNotifications.py +++ b/request-management-api/request_api/models/FOIRawRequestNotifications.py @@ -45,7 +45,7 @@ def savenotification(cls,foinotification)->DefaultMethodResult: @classmethod def dismissnotification(cls, notificationids, userid='system'): try: - db.session.query(FOIRawRequestNotification).filter(FOIRawRequestNotification.notificationid.in_(notificationids)).update({FOIRawRequestNotification.isdeleted: True, FOIRawRequestNotification.updatedby: userid, + db.session.query(FOIRawRequestNotification).filter(FOIRawRequestNotification.notificationid.in_(notificationids), FOIRawRequestNotification.isdeleted == False).update({FOIRawRequestNotification.isdeleted: True, FOIRawRequestNotification.updatedby: userid, FOIRawRequestNotification.updated_at: datetime2.now()}, synchronize_session=False) db.session.commit() return DefaultMethodResult(True,'Notifications deleted ', notificationids) diff --git a/request-management-api/request_api/models/FOIRequestNotificationUsers.py b/request-management-api/request_api/models/FOIRequestNotificationUsers.py index 9e80691ca..14239ecbd 100644 --- a/request-management-api/request_api/models/FOIRequestNotificationUsers.py +++ b/request-management-api/request_api/models/FOIRequestNotificationUsers.py @@ -81,7 +81,7 @@ def dismissnotificationbyuserandtype(cls, userid, notificationusertypelabel): @classmethod def dismissbynotificationid(cls, notificationids, userid='system'): - db.session.query(FOIRequestNotificationUser).filter(FOIRequestNotificationUser.notificationid.in_(notificationids)).update({FOIRequestNotificationUser.isdeleted: True, FOIRequestNotificationUser.updatedby: userid, + db.session.query(FOIRequestNotificationUser).filter(FOIRequestNotificationUser.notificationid.in_(notificationids), FOIRequestNotificationUser.isdeleted == False).update({FOIRequestNotificationUser.isdeleted: True, FOIRequestNotificationUser.updatedby: userid, FOIRequestNotificationUser.updated_at: datetime2.now()}, synchronize_session=False) db.session.commit() return DefaultMethodResult(True,'Notifications deleted for id',notificationids) diff --git a/request-management-api/request_api/models/FOIRequestNotifications.py b/request-management-api/request_api/models/FOIRequestNotifications.py index fc8728878..a23387e41 100644 --- a/request-management-api/request_api/models/FOIRequestNotifications.py +++ b/request-management-api/request_api/models/FOIRequestNotifications.py @@ -128,7 +128,7 @@ def getextensionnotifications(cls, extensionid): @classmethod def dismissnotification(cls, notificationids, userid='system'): try: - db.session.query(FOIRequestNotification).filter(FOIRequestNotification.notificationid.in_(notificationids)).update({FOIRequestNotification.isdeleted: True, FOIRequestNotification.updatedby: userid, + db.session.query(FOIRequestNotification).filter(FOIRequestNotification.notificationid.in_(notificationids), FOIRequestNotification.isdeleted == False).update({FOIRequestNotification.isdeleted: True, FOIRequestNotification.updatedby: userid, FOIRequestNotification.updated_at: datetime2.now()}, synchronize_session=False) db.session.commit() return DefaultMethodResult(True,'Notifications deleted ', notificationids) From 1f922c72408047262c31ad9992b5d379065b0eba Mon Sep 17 00:00:00 2001 From: Shivakumar Date: Fri, 5 Jan 2024 13:12:57 -0800 Subject: [PATCH 186/238] Remove print statements --- .../request_api/services/notificationservice.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/request-management-api/request_api/services/notificationservice.py b/request-management-api/request_api/services/notificationservice.py index f3a873c7d..346659bd8 100644 --- a/request-management-api/request_api/services/notificationservice.py +++ b/request-management-api/request_api/services/notificationservice.py @@ -276,14 +276,11 @@ def __preparenotification(self, message, requesttype, notificationtype, userid, notification.idnumber ='U-00' + str(foirequest['requestid']) mutenotification = False - print("notificationtype", notificationtype) # in notificationtype remove space and make lower case notificationtype_format = notificationtype.replace(" ", "").lower() - print ("notificationtype_format", notificationtype_format) if notificationtype_format not in notificationtypes_cache: print('Notification type not found in enum.', notificationtype) else: - print('Notification type found', notificationtype) notification.notificationtypelabel = notificationtypes_cache[notificationtype_format]['notificationtypelabel'] notification.notificationtypeid = notificationtypes_cache[notificationtype_format]['notificationtypeid'] notification.axisnumber = foirequest["axisrequestid"] From 09fcb80a63cb10a7233db6854b9b48ebe2f0b237 Mon Sep 17 00:00:00 2001 From: Richard Qi Date: Fri, 5 Jan 2024 22:43:42 -0800 Subject: [PATCH 187/238] save and update all open requests --- ...9a97f42b5f2_add_profileid_to_applicant.py} | 13 +- .../request_api/models/FOIMinistryRequests.py | 24 ++++ .../models/FOIRequestApplicantMappings.py | 4 +- .../models/FOIRequestApplicants.py | 119 ++++++++++-------- .../request_api/resources/foiapplicant.py | 19 +++ .../request_api/schemas/foiapplicant.py | 3 - .../request_api/services/applicantservice.py | 5 +- .../foirequest/requestservicebuilder.py | 2 +- .../foirequest/requestservicecreate.py | 4 +- 9 files changed, 124 insertions(+), 69 deletions(-) rename request-management-api/migrations/versions/{59a97f42b5f2_add_version_to_applicant.py => 59a97f42b5f2_add_profileid_to_applicant.py} (50%) diff --git a/request-management-api/migrations/versions/59a97f42b5f2_add_version_to_applicant.py b/request-management-api/migrations/versions/59a97f42b5f2_add_profileid_to_applicant.py similarity index 50% rename from request-management-api/migrations/versions/59a97f42b5f2_add_version_to_applicant.py rename to request-management-api/migrations/versions/59a97f42b5f2_add_profileid_to_applicant.py index 9fd31fafb..54f46603a 100644 --- a/request-management-api/migrations/versions/59a97f42b5f2_add_version_to_applicant.py +++ b/request-management-api/migrations/versions/59a97f42b5f2_add_profileid_to_applicant.py @@ -7,7 +7,7 @@ """ from alembic import op import sqlalchemy as sa - +from sqlalchemy.dialects import postgresql # revision identifiers, used by Alembic. revision = '59a97f42b5f2' @@ -18,16 +18,13 @@ def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.add_column('FOIRequestApplicants', sa.Column('version', sa.Integer(), nullable=True, default=1)) - op.add_column('FOIRequestApplicantMappings', sa.Column('foirequestapplicant_version', sa.Integer(), nullable=True)) - - op.execute('Update public."FOIRequestApplicants" set version = 1;') - op.execute('Update public."FOIRequestApplicantMappings" set foirequestapplicant_version = 1;') + op.add_column('FOIRequestApplicants', sa.Column('applicantprofileid', sa.String(length=120), nullable=True)) + #op.add_column('FOIRequestApplicants', sa.Column('isactive', sa.Boolean, unique=False, nullable=True, default=True)) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_column('FOIRequestApplicants', 'version') - op.drop_column('FOIRequestApplicantMappings', 'foirequestapplicant_version') + op.drop_column('FOIRequestApplicants', 'applicantprofileid') + #op.drop_column('FOIRequestApplicants', 'isactive') # ### end Alembic commands ### diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index c784dfed6..2f10afbf2 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -230,6 +230,30 @@ def getopenrequestsbyrequestId(cls,requestids): FOIMinistryRequest.requeststatusid != 3 ).order_by(FOIMinistryRequest.foiministryrequestid.asc(), FOIMinistryRequest.version.asc()) return [r._asdict() for r in query] + + @classmethod + def getopenrequestsbyapplicantid(cls,applicantid): + selectedcolumns = [FOIMinistryRequest.foirequest_id, FOIMinistryRequest.foiministryrequestid] + query = db.session.query( + *selectedcolumns + ).distinct( + FOIMinistryRequest.foiministryrequestid + ).join( + FOIRequestApplicantMapping, + and_( + FOIRequestApplicantMapping.foirequest_id == FOIMinistryRequest.foirequest_id, + FOIRequestApplicantMapping.foirequestversion_id == FOIMinistryRequest.foirequestversion_id, + FOIRequestApplicantMapping.requestortypeid == RequestorType['applicant'].value) + ).join( + FOIRequestApplicant, + FOIRequestApplicant.foirequestapplicantid == FOIRequestApplicantMapping.foirequestapplicantid, + ).filter( + FOIRequestApplicant.foirequestapplicantid == applicantid, + FOIMinistryRequest.requeststatusid != 3 + ).order_by( + FOIMinistryRequest.foiministryrequestid.asc(), + FOIMinistryRequest.version.asc()) + return [r._asdict() for r in query] @classmethod def getrequeststatusById(cls,ministryrequestid): diff --git a/request-management-api/request_api/models/FOIRequestApplicantMappings.py b/request-management-api/request_api/models/FOIRequestApplicantMappings.py index 782a702ec..74cdeef90 100644 --- a/request-management-api/request_api/models/FOIRequestApplicantMappings.py +++ b/request-management-api/request_api/models/FOIRequestApplicantMappings.py @@ -29,9 +29,7 @@ class FOIRequestApplicantMapping(db.Model): requestortype = relationship("RequestorType",backref=backref("RequestorTypes"),uselist=False) foirequestapplicantid = db.Column(db.Integer,ForeignKey('FOIRequestApplicants.foirequestapplicantid')) - foirequestapplicant_version = db.Column(db.Integer, ForeignKey('FOIRequestApplicants.version')) - foirequestapplicant = relationship('FOIRequestApplicant', primaryjoin="and_(FOIRequestApplicant.foirequestapplicantid==FOIRequestApplicantMapping.foirequestapplicantid, " - "FOIRequestApplicant.version==FOIRequestApplicantMapping.foirequestapplicant_version)") + foirequestapplicant = relationship("FOIRequestApplicant",backref=backref("FOIRequestApplicants"),uselist=False) foirequest_id =db.Column(db.Integer, ForeignKey('FOIRequests.foirequestid')) foirequestversion_id = db.Column(db.Integer, ForeignKey('FOIRequests.version')) diff --git a/request-management-api/request_api/models/FOIRequestApplicants.py b/request-management-api/request_api/models/FOIRequestApplicants.py index f1b0e292c..080773792 100644 --- a/request-management-api/request_api/models/FOIRequestApplicants.py +++ b/request-management-api/request_api/models/FOIRequestApplicants.py @@ -10,6 +10,7 @@ from .FOIRequestContactInformation import FOIRequestContactInformation from .FOIRequestPersonalAttributes import FOIRequestPersonalAttribute from sqlalchemy import and_, or_, func, case +import uuid class FOIRequestApplicant(db.Model): # Name of the table in our database @@ -17,7 +18,6 @@ class FOIRequestApplicant(db.Model): # Defining the columns foirequestapplicantid = db.Column(db.Integer, primary_key=True,autoincrement=True) - firstname = db.Column(db.String(50), unique=False, nullable=True) middlename = db.Column(db.String(50), unique=False, nullable=True) lastname = db.Column(db.String(50), unique=False, nullable=True) @@ -30,43 +30,64 @@ class FOIRequestApplicant(db.Model): updated_at = db.Column(db.DateTime, nullable=True) createdby = db.Column(db.String(120), unique=False, nullable=True) updatedby = db.Column(db.String(120), unique=False, nullable=True) - version = db.Column(db.Integer, unique=False, nullable=True) + applicantprofileid = db.Column(db.String(120), unique=False, nullable=True) @classmethod - def saveapplicant(cls,firstname, lastname, middlename, businessname, alsoknownas, dob, userid): - dbquery = db.session.query(FOIRequestApplicant) - ### check the applicantid instead of firstname and lastname - dbquery = dbquery.filter_by(firstname=firstname) - applicant = dbquery.filter_by(lastname=lastname) - if (applicant.count() > 0): - _applicant = { - FOIRequestApplicant.updatedby: userid, - FOIRequestApplicant.updated_at: datetime.now(), - FOIRequestApplicant.middlename: middlename, - FOIRequestApplicant.businessname: businessname, - FOIRequestApplicant.alsoknownas: alsoknownas - } - if dob is not None and dob != "": - _applicant[FOIRequestApplicant.dob] = dob - else: - _applicant[FOIRequestApplicant.dob] = None - applicant.update(_applicant) - return DefaultMethodResult(True,'Applicant updated',applicant.first().foirequestapplicantid) + def createapplicant(cls, firstname, lastname, middlename, businessname, alsoknownas, dob, userid): + applicant = FOIRequestApplicant() + applicant.createdby = userid + applicant.firstname = firstname + applicant.lastname = lastname + applicant.middlename = middlename + applicant.businessname = businessname + applicant.alsoknownas = alsoknownas + if dob is not None and dob != "": + applicant.dob = dob else: - applicant = FOIRequestApplicant() - applicant.createdby = userid - applicant.firstname = firstname - applicant.lastname = lastname - applicant.middlename = middlename - applicant.businessname = businessname - applicant.alsoknownas = alsoknownas + applicant.dob = None + db.session.add(applicant) + db.session.commit() + return DefaultMethodResult(True,'Applicant added',applicant.foirequestapplicantid) + + @classmethod + def updateapplicantprofile(cls, foirequestapplicantid, firstname, lastname, middlename, businessname, alsoknownas, dob, userid): + applicant_query = db.session.query( + FOIRequestApplicant + ).filter_by( + foirequestapplicantid = foirequestapplicantid + ) + applicant = applicant_query.first() + + # create an applicant profile id if it's not set + if(applicant.applicantprofileid is None): + # applicant.isactive = False + applicant_query.update({FOIRequestApplicant.applicantprofileid:str(uuid.uuid4())}) + + if( + applicant.firstname != firstname + or applicant.lastname != lastname + or applicant.middlename != middlename + or applicant.businessname != businessname + or applicant.alsoknownas != alsoknownas + or applicant.dob != dob + ): + _applicant = FOIRequestApplicant() + _applicant.createdby = userid + _applicant.firstname = firstname + _applicant.lastname = lastname + _applicant.middlename = middlename + _applicant.businessname = businessname + _applicant.alsoknownas = alsoknownas + _applicant.applicantprofileid = applicant.applicantprofileid if dob is not None and dob != "": - applicant.dob = dob + _applicant.dob = dob else: - applicant.dob = None - db.session.add(applicant) + _applicant.dob = None + db.session.add(_applicant) db.session.commit() - return DefaultMethodResult(True,'Applicant added',applicant.foirequestapplicantid) + return DefaultMethodResult(True,'Applicant profile updated',_applicant.foirequestapplicantid) + else: + return DefaultMethodResult(True,'No update',applicant.foirequestapplicantid) # Search applicant by email @classmethod @@ -112,7 +133,6 @@ def getapplicantbyemail(cls, email): FOIRequestApplicant.alsoknownas.label('alsoknownas'), func.to_char(FOIRequestApplicant.dob, 'YYYY-MM-DD').label('dob'), FOIRequestApplicant.businessname.label('businessname'), - FOIRequestApplicant.version.label('applicantversion'), FOIRequest.foirequestid.label('foirequestid'), FOIRequest.version.label('foirequestversion'), FOIRequest.requesttype.label('requesttype'), @@ -144,11 +164,11 @@ def getapplicantbyemail(cls, email): FOIRequestApplicantMapping.requestortypeid == 1), ).join( FOIRequestApplicant, - # FOIRequestApplicant.foirequestapplicantid == FOIRequestApplicantMapping.foirequestapplicantid - and_( - FOIRequestApplicant.foirequestapplicantid == FOIRequestApplicantMapping.foirequestapplicantid, - FOIRequestApplicant.version == FOIRequestApplicantMapping.foirequestapplicant_version - ) + FOIRequestApplicant.foirequestapplicantid == FOIRequestApplicantMapping.foirequestapplicantid + # and_( + # FOIRequestApplicant.foirequestapplicantid == FOIRequestApplicantMapping.foirequestapplicantid, + # FOIRequestApplicant.isactive != False + # ) ).join( ApplicantCategory, ApplicantCategory.applicantcategoryid == FOIRequest.applicantcategoryid @@ -298,7 +318,6 @@ def getapplicantbyemail(cls, email): func.array_agg(subquery_all.c.alsoknownas).label('alsoknownas'), func.array_agg(subquery_all.c.dob).label('dob'), func.array_agg(subquery_all.c.businessname).label('businessname'), - subquery_all.c.applicantversion, func.array_agg(subquery_all.c.foirequestid).label('foirequestid'), func.array_agg(subquery_all.c.foirequestversion).label('foirequestversion'), func.array_agg(subquery_all.c.requesttype).label('requesttype'), @@ -317,7 +336,7 @@ def getapplicantbyemail(cls, email): func.array_agg(subquery_all.c.employeenumber).label('employeenumber'), func.array_agg(subquery_all.c.correctionnumber).label('correctionnumber'), func.array_agg(subquery_all.c.phn).label('phn') - ).group_by(subquery_all.c.foirequestapplicantid, subquery_all.c.applicantversion) + ).group_by(subquery_all.c.foirequestapplicantid) applicantprofile_schema = ApplicantProfileSchema(many=True) return applicantprofile_schema.dump(query_aggregate.all()) @@ -366,7 +385,6 @@ def searchapplicant(cls, keywords): FOIRequestApplicant.alsoknownas.label('alsoknownas'), func.to_char(FOIRequestApplicant.dob, 'YYYY-MM-DD').label('dob'), FOIRequestApplicant.businessname.label('businessname'), - FOIRequestApplicant.version.label('applicantversion'), FOIRequest.foirequestid.label('foirequestid'), FOIRequest.version.label('foirequestversion'), FOIRequest.requesttype.label('requesttype'), @@ -397,11 +415,11 @@ def searchapplicant(cls, keywords): FOIRequestApplicantMapping.requestortypeid == 1), ).join( FOIRequestApplicant, - # FOIRequestApplicant.foirequestapplicantid == FOIRequestApplicantMapping.foirequestapplicantid - and_( - FOIRequestApplicant.foirequestapplicantid == FOIRequestApplicantMapping.foirequestapplicantid, - FOIRequestApplicant.version == FOIRequestApplicantMapping.foirequestapplicant_version - ) + FOIRequestApplicant.foirequestapplicantid == FOIRequestApplicantMapping.foirequestapplicantid + # and_( + # FOIRequestApplicant.foirequestapplicantid == FOIRequestApplicantMapping.foirequestapplicantid, + # FOIRequestApplicant.isactive != False + # ) ).join( ApplicantCategory, ApplicantCategory.applicantcategoryid == FOIRequest.applicantcategoryid @@ -542,7 +560,6 @@ def searchapplicant(cls, keywords): func.array_agg(subquery_all.c.alsoknownas).label('alsoknownas'), func.array_agg(subquery_all.c.dob).label('dob'), func.array_agg(subquery_all.c.businessname).label('businessname'), - subquery_all.c.applicantversion, func.array_agg(subquery_all.c.foirequestid).label('foirequestid'), func.array_agg(subquery_all.c.foirequestversion).label('foirequestversion'), func.array_agg(subquery_all.c.requesttype).label('requesttype'), @@ -561,7 +578,7 @@ def searchapplicant(cls, keywords): func.array_agg(subquery_all.c.employeenumber).label('employeenumber'), func.array_agg(subquery_all.c.correctionnumber).label('correctionnumber'), func.array_agg(subquery_all.c.phn).label('phn') - ).group_by(subquery_all.c.foirequestapplicantid, subquery_all.c.applicantversion) + ).group_by(subquery_all.c.foirequestapplicantid) applicantprofile_schema = ApplicantProfileSchema(many=True) return applicantprofile_schema.dump(query_aggregate.all()) @@ -601,6 +618,6 @@ class Meta: class ApplicantProfileSchema(ma.Schema): class Meta: fields = ('foirequestapplicantid','firstname','middlename','lastname','alsoknownas','dob', - 'businessname','applicantversion','foirequestid','foirequestversion','requesttype', - 'applicantcategory','email','address','city','province','postal','country','homephone','workphone','workphone2','mobilephone', - 'othercontactinfo','employeenumber','correctionnumber','phn') + 'businessname','foirequestid','foirequestversion','requesttype','applicantcategory', + 'email','address','city','province','postal','country','homephone','workphone', + 'workphone2','mobilephone','othercontactinfo','employeenumber','correctionnumber','phn') diff --git a/request-management-api/request_api/resources/foiapplicant.py b/request-management-api/request_api/resources/foiapplicant.py index 05fb4ff8d..9f039e5f3 100644 --- a/request-management-api/request_api/resources/foiapplicant.py +++ b/request-management-api/request_api/resources/foiapplicant.py @@ -111,3 +111,22 @@ def post(): except BusinessException as exception: return {'status': exception.status_code, 'message':exception.message}, 500 +@cors_preflight('POST,OPTIONS') +@API.route('/foiapplicants/testsave') +class EventPagination(Resource): + """ Saves applicant info and request specific contact info for all open requests associated to an applicant + """ + @staticmethod + @TRACER.trace() + @cross_origin(origins=allowedorigins()) + @cors_preflight('POST,OPTIONS') + def post(): + try: + applicant = FOIRequestApplicantSchema().load(request.get_json()) + result = applicantservice().saveapplicantinfo(applicant, AuthHelper.getuserid()) + if result.success: + return {'status': result.success, 'message':result.message,'id':result.identifier} , 200 + else: + return {'status': False, 'message':EXCEPTION_MESSAGE_NOT_FOUND}, 404 + except BusinessException as exception: + return {'status': exception.status_code, 'message':exception.message}, 500 \ No newline at end of file diff --git a/request-management-api/request_api/schemas/foiapplicant.py b/request-management-api/request_api/schemas/foiapplicant.py index 517d9bb93..cd62b8140 100644 --- a/request-management-api/request_api/schemas/foiapplicant.py +++ b/request-management-api/request_api/schemas/foiapplicant.py @@ -27,13 +27,10 @@ class Meta: # pylint: disable=too-few-public-methods # correctionalServiceNumber = fields.Str(data_key="correctionalServiceNumber",allow_none=True, validate=[validate.Length(max=50, error=MAX_EXCEPTION_MESSAGE)]) # publicServiceEmployeeNumber = fields.Str(data_key="publicServiceEmployeeNumber",allow_none=True, validate=[validate.Length(max=50, error=MAX_EXCEPTION_MESSAGE)]) - foiRequestApplicantID = fields.Int(data_key="foiRequestApplicantID",required=False,allow_none=True) foirequestID = fields.List(fields.Int(),data_key="foirequestID",required=True,allow_none=False) - additionalPersonalInfo = fields.Nested(FOIAdditionallPersonalInfoWrapperSchema,required=False,allow_none=True) - \ No newline at end of file diff --git a/request-management-api/request_api/services/applicantservice.py b/request-management-api/request_api/services/applicantservice.py index ed5cdaeb3..5eb5985bf 100644 --- a/request-management-api/request_api/services/applicantservice.py +++ b/request-management-api/request_api/services/applicantservice.py @@ -36,7 +36,8 @@ def searchapplicant(self, keywords): return applicantqueue def saveapplicantinfo(self, applicantschema, userid): - FOIRequestApplicant.saveapplicant( + applicant = FOIRequestApplicant.updateapplicantprofile( + applicantschema['foiRequestApplicantID'], applicantschema['firstName'], applicantschema['lastName'], applicantschema['middleName'], @@ -46,6 +47,8 @@ def saveapplicantinfo(self, applicantschema, userid): userid ) # replace with applicant id once new save function is written requests = FOIMinistryRequest.getopenrequestsbyrequestId(applicantschema['foirequestID']) + applicantschema['foiRequestApplicantID'] = applicant.identifier + # requests = FOIMinistryRequest.getopenrequestsbyapplicantid(applicantschema['foiRequestApplicantID']) for request in requests: requestschema = requestservicegetter().getrequest(request['foirequest_id'], request['foiministryrequestid']) requestschema.update(applicantschema) diff --git a/request-management-api/request_api/services/foirequest/requestservicebuilder.py b/request-management-api/request_api/services/foirequest/requestservicebuilder.py index 4f6db7aa5..0f214e3ba 100644 --- a/request-management-api/request_api/services/foirequest/requestservicebuilder.py +++ b/request-management-api/request_api/services/foirequest/requestservicebuilder.py @@ -109,7 +109,7 @@ def createcontactinformation(self,dataformat, name, value, contacttypes, userid) def createapplicant(self,firstname, lastname, appltcategory, userid, middlename = None,businessname = None, alsoknownas = None, dob = None): requestapplicant = FOIRequestApplicantMapping() - _applicant = FOIRequestApplicant().saveapplicant(firstname, lastname, middlename, businessname, alsoknownas, dob, userid) + _applicant = FOIRequestApplicant().createapplicant(firstname, lastname, middlename, businessname, alsoknownas, dob, userid) requestapplicant.foirequestapplicantid = _applicant.identifier if appltcategory is not None: requestertype = RequestorType().getrequestortype(appltcategory) diff --git a/request-management-api/request_api/services/foirequest/requestservicecreate.py b/request-management-api/request_api/services/foirequest/requestservicecreate.py index e33828807..cec25115b 100644 --- a/request-management-api/request_api/services/foirequest/requestservicecreate.py +++ b/request-management-api/request_api/services/foirequest/requestservicecreate.py @@ -61,7 +61,7 @@ def saverequestversion(self,foirequestschema, foirequestid , ministryid, userid) else: return _foirequest self.__disablewatchers(ministryid, foirequestschema, userid) - result = self.saverequest(foirequestschema, userid, foirequestid,ministryid,filenumber,activeversion,_foirequest["foirawrequestid"],_foirequest["wfinstanceid"]) + result = self.saverequest(foirequestschema, userid, foirequestid,ministryid,filenumber,activeversion,_foirequest["foirawrequestid"],_foirequest["wfinstanceid"]) if result.success == True: FOIMinistryRequest.deActivateFileNumberVersion(ministryid, filenumber, userid) return result @@ -127,7 +127,7 @@ def __prepareapplicants(self, foirequestschema, userid): requestapplicantarr = [] selfalsoknownas=None selfdob=None - if foirequestschema.get("additionalPersonalInfo") is not None and foirequestschema.get('requeststatusid') == 1: + if foirequestschema.get("additionalPersonalInfo") is not None and foirequestschema.get('requeststatusid') == 1: if foirequestschema.get('foiRequestApplicantID', None): requestapplicant = FOIRequestApplicantMapping() requestapplicant.foirequestapplicantid = foirequestschema['foiRequestApplicantID'] From a32c3f78a409d0ee1a99563e62781c5be091b0b7 Mon Sep 17 00:00:00 2001 From: Shivakumar Date: Mon, 8 Jan 2024 12:37:50 -0800 Subject: [PATCH 188/238] All notification/user labels must be fetched from cache first --- .../notifications/notificationconfig.py | 37 +++++++++++++++---- .../services/notificationservice.py | 9 +---- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/request-management-api/request_api/services/notifications/notificationconfig.py b/request-management-api/request_api/services/notifications/notificationconfig.py index da099251d..7bcc08139 100644 --- a/request-management-api/request_api/services/notifications/notificationconfig.py +++ b/request-management-api/request_api/services/notifications/notificationconfig.py @@ -5,17 +5,30 @@ import os from request_api.models.NotificationTypes import NotificationType from request_api.models.NotificationUserTypes import NotificationUserType +notificationuserfile = open('common/notificationusertypes.json', encoding="utf8") +notificationusertypes_cache = json.load(notificationuserfile) + +notificationfile = open('common/notificationtypes.json', encoding="utf8") +notificationtypes_cache = json.load(notificationfile) class notificationconfig: """ Notfication config """ + # This method is used to get the notification user type label + # It first tries to get the notification user type label from the cache + # If it is not found in the cache, it fetches it from the DB def getnotificationtypelabel(self, notificationtype): - id = NotificationType().getnotificationtypeid(notificationtype) - if id is not None: - return id['notificationtypelabel'] - return 0 + notificationtype_format = notificationtype.replace(" ", "").lower() + if notificationtype_format in notificationtypes_cache: + return notificationtypes_cache[notificationtype_format]['notificationtypelabel'] + else: + print("Notification type not found in cache. Fetching from DB", notificationtype) + id = NotificationType().getnotificationtypeid(notificationtype) + if id is not None: + return id['notificationtypelabel'] + return 0 def getnotificationtypeid(self, notificationtype): id = NotificationType().getnotificationtypeid(notificationtype) @@ -23,11 +36,19 @@ def getnotificationtypeid(self, notificationtype): return id['notificationtypeid'] return 0 + # This method is used to get the notification user type label + # It first tries to get the notification user type label from the cache + # If it is not found in the cache, it fetches it from the DB def getnotificationusertypelabel(self, notificationusertype): - id = NotificationUserType().getnotificationusertypesid(notificationusertype) - if id is not None: - return id['notificationusertypelabel'] - return 0 + notificationusertype_format = notificationusertype.replace(" ", "").lower() + if notificationusertype_format in notificationusertypes_cache: + return notificationusertypes_cache[notificationusertype_format]['notificationusertypelabel'] + else: + print("Notification user type not found in cache. Fetching from DB", notificationusertype) + id = NotificationUserType().getnotificationusertypesid(notificationusertype) + if id is not None: + return id['notificationusertypelabel'] + return 0 def getnotificationusertypeid(self, notificationusertype): id = NotificationUserType().getnotificationusertypesid(notificationusertype) diff --git a/request-management-api/request_api/services/notificationservice.py b/request-management-api/request_api/services/notificationservice.py index 346659bd8..cd518d5e6 100644 --- a/request-management-api/request_api/services/notificationservice.py +++ b/request-management-api/request_api/services/notificationservice.py @@ -276,13 +276,8 @@ def __preparenotification(self, message, requesttype, notificationtype, userid, notification.idnumber ='U-00' + str(foirequest['requestid']) mutenotification = False - # in notificationtype remove space and make lower case - notificationtype_format = notificationtype.replace(" ", "").lower() - if notificationtype_format not in notificationtypes_cache: - print('Notification type not found in enum.', notificationtype) - else: - notification.notificationtypelabel = notificationtypes_cache[notificationtype_format]['notificationtypelabel'] - notification.notificationtypeid = notificationtypes_cache[notificationtype_format]['notificationtypeid'] + notification.notificationtypelabel = notificationconfig().getnotificationtypelabel(notificationtype) + notification.notificationtypeid = notificationconfig().getnotificationtypeid(notificationtype) notification.axisnumber = foirequest["axisrequestid"] notification.version = foirequest["version"] notification.createdby = userid From a65a00058f846d4cc9e373cc34fbad7ab064bb15 Mon Sep 17 00:00:00 2001 From: Shivakumar Date: Mon, 8 Jan 2024 12:43:24 -0800 Subject: [PATCH 189/238] Update None type --- .../services/notifications/notificationconfig.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/request-management-api/request_api/services/notifications/notificationconfig.py b/request-management-api/request_api/services/notifications/notificationconfig.py index 7bcc08139..5801726d9 100644 --- a/request-management-api/request_api/services/notifications/notificationconfig.py +++ b/request-management-api/request_api/services/notifications/notificationconfig.py @@ -28,13 +28,13 @@ def getnotificationtypelabel(self, notificationtype): id = NotificationType().getnotificationtypeid(notificationtype) if id is not None: return id['notificationtypelabel'] - return 0 + return None def getnotificationtypeid(self, notificationtype): id = NotificationType().getnotificationtypeid(notificationtype) if id is not None: return id['notificationtypeid'] - return 0 + return None # This method is used to get the notification user type label # It first tries to get the notification user type label from the cache @@ -48,13 +48,13 @@ def getnotificationusertypelabel(self, notificationusertype): id = NotificationUserType().getnotificationusertypesid(notificationusertype) if id is not None: return id['notificationusertypelabel'] - return 0 + return None def getnotificationusertypeid(self, notificationusertype): id = NotificationUserType().getnotificationusertypesid(notificationusertype) if id is not None: return id['notificationusertypeid'] - return 0 + return None def getnotificationdays(self): if 'FOI_NOTIFICATION_DAYS' in os.environ and os.getenv('FOI_NOTIFICATION_DAYS') != '': From 2f3a56c5802e7fed44cfc0ca96125767b66748fa Mon Sep 17 00:00:00 2001 From: divyav-aot Date: Mon, 8 Jan 2024 16:15:26 -0500 Subject: [PATCH 190/238] fixes to notificationtypeid=null, removed logs --- .../models/FOIRawRequestNotifications.py | 1 + .../request_api/models/FOIRawRequests.py | 8 ++-- .../models/FOIRequestNotificationUsers.py | 2 +- .../models/FOIRequestNotifications.py | 2 +- .../request_api/services/events/assignment.py | 4 +- .../request_api/services/events/cfrdate.py | 20 +++------ .../request_api/services/events/cfrfeeform.py | 4 +- .../services/events/divisiondate.py | 8 ++-- .../request_api/services/events/email.py | 4 +- .../request_api/services/events/extension.py | 4 +- .../services/events/legislativedate.py | 15 +++---- .../request_api/services/events/payment.py | 11 +++-- .../services/events/section5pending.py | 8 ++-- .../request_api/services/events/state.py | 8 ++-- .../request_api/services/eventservice.py | 21 ---------- .../services/notificationservice.py | 42 +++++++++---------- 16 files changed, 72 insertions(+), 90 deletions(-) diff --git a/request-management-api/request_api/models/FOIRawRequestNotifications.py b/request-management-api/request_api/models/FOIRawRequestNotifications.py index d95a1fac4..cb21f0769 100644 --- a/request-management-api/request_api/models/FOIRawRequestNotifications.py +++ b/request-management-api/request_api/models/FOIRawRequestNotifications.py @@ -27,6 +27,7 @@ class FOIRawRequestNotification(db.Model): updated_at = db.Column(db.DateTime, nullable=True) updatedby = db.Column(db.String(120), unique=False, nullable=True) + notificationtypeid = db.Column(db.Integer, nullable=False) notificationtypelabel = db.Column(db.Integer, nullable=False) notificationusers = db.relationship('FOIRawRequestNotificationUser', backref='FOIRawRequestNotifications', lazy='dynamic') diff --git a/request-management-api/request_api/models/FOIRawRequests.py b/request-management-api/request_api/models/FOIRawRequests.py index 332c9278f..7a244d0c8 100644 --- a/request-management-api/request_api/models/FOIRawRequests.py +++ b/request-management-api/request_api/models/FOIRawRequests.py @@ -877,14 +877,14 @@ def getfilterforrequeststate(cls, params, includeclosed): #request state: unopened, call for records, etc. requeststatecondition = [] for state in params['requeststate']: - if(state == '3'): + if(state == StateName.closed.name): requeststatecondition.append(FOIRawRequest.status == StateName.closed.value) includeclosed = True - elif(state == '4'): + elif(state == StateName.redirect.name): requeststatecondition.append(FOIRawRequest.status == StateName.redirect.value) - elif(state == '5'): + elif(state == StateName.unopened.name): requeststatecondition.append(FOIRawRequest.status == StateName.unopened.value) - elif(state == '6'): + elif(state == StateName.intakeinprogress.name): requeststatecondition.append(FOIRawRequest.status == StateName.intakeinprogress.value) if(len(requeststatecondition) == 0): diff --git a/request-management-api/request_api/models/FOIRequestNotificationUsers.py b/request-management-api/request_api/models/FOIRequestNotificationUsers.py index 14239ecbd..9e80691ca 100644 --- a/request-management-api/request_api/models/FOIRequestNotificationUsers.py +++ b/request-management-api/request_api/models/FOIRequestNotificationUsers.py @@ -81,7 +81,7 @@ def dismissnotificationbyuserandtype(cls, userid, notificationusertypelabel): @classmethod def dismissbynotificationid(cls, notificationids, userid='system'): - db.session.query(FOIRequestNotificationUser).filter(FOIRequestNotificationUser.notificationid.in_(notificationids), FOIRequestNotificationUser.isdeleted == False).update({FOIRequestNotificationUser.isdeleted: True, FOIRequestNotificationUser.updatedby: userid, + db.session.query(FOIRequestNotificationUser).filter(FOIRequestNotificationUser.notificationid.in_(notificationids)).update({FOIRequestNotificationUser.isdeleted: True, FOIRequestNotificationUser.updatedby: userid, FOIRequestNotificationUser.updated_at: datetime2.now()}, synchronize_session=False) db.session.commit() return DefaultMethodResult(True,'Notifications deleted for id',notificationids) diff --git a/request-management-api/request_api/models/FOIRequestNotifications.py b/request-management-api/request_api/models/FOIRequestNotifications.py index a23387e41..fc8728878 100644 --- a/request-management-api/request_api/models/FOIRequestNotifications.py +++ b/request-management-api/request_api/models/FOIRequestNotifications.py @@ -128,7 +128,7 @@ def getextensionnotifications(cls, extensionid): @classmethod def dismissnotification(cls, notificationids, userid='system'): try: - db.session.query(FOIRequestNotification).filter(FOIRequestNotification.notificationid.in_(notificationids), FOIRequestNotification.isdeleted == False).update({FOIRequestNotification.isdeleted: True, FOIRequestNotification.updatedby: userid, + db.session.query(FOIRequestNotification).filter(FOIRequestNotification.notificationid.in_(notificationids)).update({FOIRequestNotification.isdeleted: True, FOIRequestNotification.updatedby: userid, FOIRequestNotification.updated_at: datetime2.now()}, synchronize_session=False) db.session.commit() return DefaultMethodResult(True,'Notifications deleted ', notificationids) diff --git a/request-management-api/request_api/services/events/assignment.py b/request-management-api/request_api/services/events/assignment.py index b8f74dea1..538317aba 100644 --- a/request-management-api/request_api/services/events/assignment.py +++ b/request-management-api/request_api/services/events/assignment.py @@ -7,6 +7,7 @@ from request_api.models.FOIRawRequests import FOIRawRequest from request_api.models.FOIMinistryRequests import FOIMinistryRequest from request_api.models.FOIRequestStatus import FOIRequestStatus +from request_api.models.NotificationTypes import NotificationType import json from request_api.models.default_method_result import DefaultMethodResult from request_api.utils.enums import CommentType @@ -38,7 +39,8 @@ def createassignmentevent(self, requestid, requesttype, userid, isministryuser,a def __createnotification(self, requestid, requesttype, userid, isministryuser): notification = self.__preparenotification() - return notificationservice().createnotification({"message" : notification}, requestid, requesttype, self.__assignmenttype(isministryuser), userid) + notificationtype = NotificationType().getnotificationtypeid(self.__assignmenttype(isministryuser)) + return notificationservice().createnotification({"message" : notification}, requestid, requesttype, notificationtype, userid) def __createnotificationforremoval(self, requestid, requesttype, userid, username, previousassignee): notification = self.__preparenotification(username, True) diff --git a/request-management-api/request_api/services/events/cfrdate.py b/request-management-api/request_api/services/events/cfrdate.py index 82f5a9182..6d742234a 100644 --- a/request-management-api/request_api/services/events/cfrdate.py +++ b/request-management-api/request_api/services/events/cfrdate.py @@ -6,6 +6,7 @@ from request_api.services.commentservice import commentservice from request_api.models.FOIMinistryRequests import FOIMinistryRequest from request_api.models.FOIRequestComments import FOIRequestComment +from request_api.models.NotificationTypes import NotificationType import json from request_api.models.default_method_result import DefaultMethodResult from enum import Enum @@ -25,37 +26,28 @@ class cfrdateevent(duecalculator): def createdueevent(self): try: _today = self.gettoday() - time = t.time() notificationservice().dismissremindernotification("ministryrequest", self.__notificationtype()) - dismissremindernotification_time = t.time() - print("dismissremindernotification_time: %s" % (dismissremindernotification_time - time)) ca_holidays = self.getholidays() - time = t.time() _upcomingdues = FOIMinistryRequest.getupcomingcfrduerecords() - getupcomingcfrduerecords_time = t.time() - print("getupcomingcfrduerecords_time: %s" % (getupcomingcfrduerecords_time - time)) - + notificationtype = NotificationType().getnotificationtypeid(self.__notificationtype()) for entry in _upcomingdues: _duedate = self.formatduedate(entry['cfrduedate']) message = None if _duedate == _today: message = self.__todayduemessage() elif self.getpreviousbusinessday(entry['cfrduedate'],ca_holidays) == _today: - message = self.__upcomingduemessage(_duedate) - createnotification_time = t.time() - self.__createnotification(message,entry['foiministryrequestid']) + message = self.__upcomingduemessage(_duedate) + self.__createnotification(message,entry['foiministryrequestid'], notificationtype) self.__createcomment(entry, message) - createnotification_time = t.time() - createnotification_time - print("createnotification_time: %s" % createnotification_time) return DefaultMethodResult(True,'CFR reminder notifications created',_today) except BusinessException as exception: current_app.logger.error("%s,%s" % ('CFR reminder Notification Error', exception.message)) return DefaultMethodResult(False,'CFR reminder notifications failed',_today) - def __createnotification(self, message, requestid): + def __createnotification(self, message, requestid, notificationtype): if message is not None: - return notificationservice().createremindernotification({"message" : message}, requestid, "ministryrequest", self.__notificationtype(), self.__defaultuserid()) + return notificationservice().createremindernotification({"message" : message}, requestid, "ministryrequest", notificationtype, self.__defaultuserid()) def __createcomment(self, entry, message): if message is not None: diff --git a/request-management-api/request_api/services/events/cfrfeeform.py b/request-management-api/request_api/services/events/cfrfeeform.py index d82e57806..e98711244 100644 --- a/request-management-api/request_api/services/events/cfrfeeform.py +++ b/request-management-api/request_api/services/events/cfrfeeform.py @@ -6,6 +6,7 @@ from request_api.services.commentservice import commentservice from request_api.services.cfrfeeservice import cfrfeeservice from request_api.services.notificationservice import notificationservice +from request_api.models.NotificationTypes import NotificationType import json from request_api.models.default_method_result import DefaultMethodResult from enum import Enum @@ -60,7 +61,8 @@ def __createcomment(self, requestid, state, userid, username, updatedamounts=Non def __createnotification(self, requestid, state, userid): notification = self.__preparenotification(state) - return notificationservice().createnotification({"message" : notification}, requestid, "ministryrequest", "CFR Fee Form", userid) + notificationtype = NotificationType().getnotificationtypeid("CFR Fee Form") + return notificationservice().createnotification({"message" : notification}, requestid, "ministryrequest", notificationtype, userid) def __preparecomment(self, requestid, state, username, updatedamounts): comment = {"comment": self.__commentmessage(state, username, updatedamounts)} diff --git a/request-management-api/request_api/services/events/divisiondate.py b/request-management-api/request_api/services/events/divisiondate.py index ceab3a561..c208581dd 100644 --- a/request-management-api/request_api/services/events/divisiondate.py +++ b/request-management-api/request_api/services/events/divisiondate.py @@ -5,6 +5,7 @@ from request_api.services.commentservice import commentservice from request_api.models.FOIMinistryRequests import FOIMinistryRequest from request_api.models.FOIRequestComments import FOIRequestComment +from request_api.models.NotificationTypes import NotificationType import json from request_api.models.default_method_result import DefaultMethodResult from enum import Enum @@ -26,6 +27,7 @@ def createdueevent(self): notificationservice().dismissremindernotification("ministryrequest", self.__notificationtype()) ca_holidays = self.getholidays() _upcomingdues = FOIMinistryRequest.getupcomingdivisionduerecords() + notificationtype = NotificationType().getnotificationtypeid(self.__notificationtype()) for entry in _upcomingdues: _duedate = self.formatduedate(entry['duedate']) message = None @@ -33,16 +35,16 @@ def createdueevent(self): message = self.__todayduemessage(entry) elif self.getpreviousbusinessday(entry['duedate'],ca_holidays) == _today: message = self.__upcomingduemessage(entry) - self.__createnotification(message,entry['foiministryrequestid']) + self.__createnotification(message,entry['foiministryrequestid'], notificationtype) self.__createcomment(entry, message) return DefaultMethodResult(True,'Division reminder notifications created',_today) except BusinessException as exception: current_app.logger.error("%s,%s" % ('Legislative reminder Notification Error', exception.message)) return DefaultMethodResult(False,'Division reminder notifications failed',_today) - def __createnotification(self, message, requestid): + def __createnotification(self, message, requestid, notificationtype): if message is not None: - return notificationservice().createnotification({"message" : message}, requestid, "ministryrequest", self.__notificationtype(), self.__defaultuserid(), False) + return notificationservice().createnotification({"message" : message}, requestid, "ministryrequest", notificationtype, self.__defaultuserid(), False) def __createcomment(self, entry, message): if message is not None: diff --git a/request-management-api/request_api/services/events/email.py b/request-management-api/request_api/services/events/email.py index 395d84fb8..8011ad324 100644 --- a/request-management-api/request_api/services/events/email.py +++ b/request-management-api/request_api/services/events/email.py @@ -7,6 +7,7 @@ from request_api.models.FOIRawRequests import FOIRawRequest from request_api.models.FOIMinistryRequests import FOIMinistryRequest from request_api.models.FOIRequestStatus import FOIRequestStatus +from request_api.models.NotificationTypes import NotificationType import json from request_api.models.default_method_result import DefaultMethodResult import logging @@ -35,7 +36,8 @@ def __createcomment(self, requestid, requesttype, stage, reason, userid): def __createnotification(self, requestid, requesttype, stage): notification = self.__preparenotification(stage) - return notificationservice().createnotification({"message" : notification}, requestid, requesttype, "Email Failure", self.__defaultuserid()) + notificationtype = NotificationType().getnotificationtypeid("Email Failure") + return notificationservice().createnotification({"message" : notification}, requestid, requesttype, notificationtype, self.__defaultuserid()) def __preparenotification(self, stage): return self.__notificationmessage(stage) diff --git a/request-management-api/request_api/services/events/extension.py b/request-management-api/request_api/services/events/extension.py index 497ad2bcb..dec4a8447 100644 --- a/request-management-api/request_api/services/events/extension.py +++ b/request-management-api/request_api/services/events/extension.py @@ -8,6 +8,7 @@ from request_api.models.FOIMinistryRequests import FOIMinistryRequest from request_api.models.FOIRequestComments import FOIRequestComment from request_api.models.FOIRequestNotifications import FOIRequestNotification +from request_api.models.NotificationTypes import NotificationType import json from request_api.models.default_method_result import DefaultMethodResult from enum import Enum @@ -72,7 +73,8 @@ def createnotification(self, ministryrequestid, extensionid, curextension, preve notification = self.__preparenotification(extensionsummary) if notificationandcleanup == True: self.__deleteextensionnotification(extensionid) - return notificationservice().createnotification({"extensionid": extensionid, "message": notification}, ministryrequestid, "ministryrequest", "Extension", userid, False) + notificationtype = NotificationType().getnotificationtypeid("Extension") + return notificationservice().createnotification({"extensionid": extensionid, "message": notification}, ministryrequestid, "ministryrequest", notificationtype, userid, False) def __deleteaxisextensionnotifications(self, notificationids): notificationservice().dismissnotificationbyid("ministryrequest", notificationids) diff --git a/request-management-api/request_api/services/events/legislativedate.py b/request-management-api/request_api/services/events/legislativedate.py index c459a1c7b..56885014c 100644 --- a/request-management-api/request_api/services/events/legislativedate.py +++ b/request-management-api/request_api/services/events/legislativedate.py @@ -6,6 +6,7 @@ from request_api.services.commentservice import commentservice from request_api.models.FOIMinistryRequests import FOIMinistryRequest from request_api.models.FOIRequestComments import FOIRequestComment +from request_api.models.NotificationTypes import NotificationType import json from request_api.models.default_method_result import DefaultMethodResult from enum import Enum @@ -29,6 +30,7 @@ def createdueevent(self): notificationservice().dismissremindernotification("ministryrequest", self.__notificationtype()) ca_holidays = self.getholidays() _upcomingdues = FOIMinistryRequest.getupcominglegislativeduerecords() + notificationtype = NotificationType().getnotificationtypeid(self.__notificationtype()) for entry in _upcomingdues: _duedate = self.formatduedate(entry['duedate']) message = None @@ -36,22 +38,17 @@ def createdueevent(self): message = self.__todayduemessage() elif self.getpreviousbusinessday(entry['duedate'],ca_holidays) == _today or self.getbusinessdaysbetween(entry['duedate'],_today) == 5: message = self.__upcomingduemessage(_duedate) - createnotification_time = t.time() - self.__createnotification(message,entry['foiministryrequestid']) - createnotification_time = t.time() - createnotification_time - print("createnotification_time: %s" % createnotification_time) - createcomment_time = t.time() + + self.__createnotification(message,entry['foiministryrequestid'], notificationtype) self.__createcomment(entry, message) - createcomment_time = t.time() - createcomment_time - print("createcomment_time: %s" % createcomment_time) return DefaultMethodResult(True,'Legislative reminder notifications created',_today) except BusinessException as exception: current_app.logger.error("%s,%s" % ('Legislative reminder Notification Error', exception.message)) return DefaultMethodResult(False,'Legislative reminder notifications failed',_today) - def __createnotification(self, message, requestid): + def __createnotification(self, message, requestid, notificationtype): if message is not None: - return notificationservice().createnotification({"message" : message}, requestid, "ministryrequest", self.__notificationtype(), self.__defaultuserid(), False) + return notificationservice().createnotification({"message" : message}, requestid, "ministryrequest", notificationtype, self.__defaultuserid(), False) def __createcomment(self, entry, message): if message is not None: diff --git a/request-management-api/request_api/services/events/payment.py b/request-management-api/request_api/services/events/payment.py index 6263e5a8a..f22cbb83b 100644 --- a/request-management-api/request_api/services/events/payment.py +++ b/request-management-api/request_api/services/events/payment.py @@ -6,6 +6,7 @@ from request_api.models.FOIMinistryRequests import FOIMinistryRequest from request_api.models.FOIRawRequests import FOIRawRequest from request_api.models.FOIRequestStatus import FOIRequestStatus +from request_api.models.NotificationTypes import NotificationType import json from request_api.models.default_method_result import DefaultMethodResult from enum import Enum @@ -46,6 +47,7 @@ def createpaymentreminderevent(self): notificationservice().dismissremindernotification("rawrequest", self.__notificationtype()) eventtype = PaymentEventType.reminder.value _onholdrequests = FOIRawRequest.getappfeeowingrequests() + notificationtype = NotificationType().getnotificationtypeid(self.__notificationtype()) for entry in _onholdrequests: _dateofstatechange = datetimehandler().formatdate(entry['updated_at']) businessdayselapsed = duecalculator().getbusinessdaysbetween(_dateofstatechange) @@ -57,7 +59,7 @@ def createpaymentreminderevent(self): commentexists = True if not commentexists: self.__createcommentforrawrequest(entry['requestid'], eventtype) - self.__createnotificationforrawrequest(entry['requestid'], eventtype) + self.__createnotificationforrawrequest(entry['requestid'], eventtype, notificationtype) return DefaultMethodResult(True,'Payment reminder notifications created',_today) except BusinessException as exception: current_app.logger.error("%s,%s" % ('Payment reminder Notification Error', exception.message)) @@ -67,17 +69,18 @@ def __createcommentforrawrequest(self, requestid, eventtype): comment = self.__preparecomment(requestid, eventtype) return commentservice().createrawrequestcomment(comment, "system", 2) - def __createnotificationforrawrequest(self, requestid, eventtype): + def __createnotificationforrawrequest(self, requestid, eventtype, notificationtype): notification = self.__preparenotification(requestid, eventtype) - return notificationservice().createnotification({"message" : notification}, requestid, "rawrequest", self.__notificationtype(), "system") + return notificationservice().createnotification({"message" : notification}, requestid, "rawrequest", notificationtype, "system") def __createcomment(self, requestid, eventtype): comment = self.__preparecomment(requestid, eventtype) return commentservice().createministryrequestcomment(comment, self.__defaultuserid(), 2) def __createnotification(self, requestid, eventtype): + notificationtype = NotificationType().getnotificationtypeid(self.__notificationtype()) notification = self.__preparenotification(requestid, eventtype) - return notificationservice().createnotification({"message" : notification}, requestid, "ministryrequest", "Payment", self.__defaultuserid()) + return notificationservice().createnotification({"message" : notification}, requestid, "ministryrequest", notificationtype, self.__defaultuserid()) def __preparenotification(self, requestid, eventtype): return self.__notificationmessage(requestid, eventtype) diff --git a/request-management-api/request_api/services/events/section5pending.py b/request-management-api/request_api/services/events/section5pending.py index 20450500e..84e6897f5 100644 --- a/request-management-api/request_api/services/events/section5pending.py +++ b/request-management-api/request_api/services/events/section5pending.py @@ -4,6 +4,7 @@ from request_api.services.notificationservice import notificationservice from request_api.services.commentservice import commentservice from request_api.models.FOIRawRequests import FOIRawRequest +from request_api.models.NotificationTypes import NotificationType from request_api.models.default_method_result import DefaultMethodResult from enum import Enum from request_api.exceptions import BusinessException @@ -20,6 +21,7 @@ def createdueevent(self): _today = self.gettoday() notificationservice().dismissremindernotification("rawrequest", self.__notificationtype()) section5pendings = FOIRawRequest.getlatestsection5pendings() + notificationtype = NotificationType().getnotificationtypeid(self.__notificationtype()) for entry in section5pendings: _dateofstatechange = datetimehandler().formatdate(entry['created_at']) businessdayselapsed = self.getbusinessdaysbetween(_dateofstatechange) @@ -32,15 +34,15 @@ def createdueevent(self): commentexists = True if not commentexists: self.__createcomment(entry, message) - self.__createnotification(message, entry['requestid']) + self.__createnotification(message, entry['requestid'], notificationtype) return DefaultMethodResult(True,'Section 5 Pending passed due notification created',_today) except BusinessException as exception: current_app.logger.error("%s,%s" % ('Section 5 Pending passed due notification Error', exception.message)) return DefaultMethodResult(False,'Section 5 Pending passed due notification failed',_today) - def __createnotification(self, message, requestid): + def __createnotification(self, message, requestid, notificationtype): if message is not None: - return notificationservice().createremindernotification({"message" : message}, requestid, "rawrequest", self.__notificationtype(), self.__defaultuserid()) + return notificationservice().createremindernotification({"message" : message}, requestid, "rawrequest", notificationtype, self.__defaultuserid()) def __createcomment(self, entry, message): if message is not None: diff --git a/request-management-api/request_api/services/events/state.py b/request-management-api/request_api/services/events/state.py index 72cdaa439..877009889 100644 --- a/request-management-api/request_api/services/events/state.py +++ b/request-management-api/request_api/services/events/state.py @@ -7,6 +7,7 @@ from request_api.models.FOIRawRequests import FOIRawRequest from request_api.models.FOIMinistryRequests import FOIMinistryRequest from request_api.models.FOIRequestStatus import FOIRequestStatus +from request_api.models.NotificationTypes import NotificationType import json from request_api.models.default_method_result import DefaultMethodResult from request_api.utils.enums import StateName @@ -62,6 +63,7 @@ def __createnotification(self, requestid, state, requesttype, userid): if state == StateName.callforrecords.value and requesttype == "ministryrequest": foirequest = notificationservice().getrequest(requestid, requesttype) _notificationtype = "Group Members" if foirequest['assignedministryperson'] is None else "State" + notificationtype = NotificationType().getnotificationtypeid(_notificationtype) notification = self.__preparenotification(state) if state == StateName.response.value and requesttype == "ministryrequest": signgoffapproval = FOIMinistryRequest().getrequest(requestid)['ministrysignoffapproval'] @@ -72,12 +74,12 @@ def __createnotification(self, requestid, state, requesttype, userid): if state == StateName.archived.value: _openedministries = FOIMinistryRequest.getministriesopenedbyuid(requestid) for ministry in _openedministries: - response = notificationservice().createnotification({"message" : notification}, ministry["ministryrequestid"], 'ministryrequest', "State", userid) + response = notificationservice().createnotification({"message" : notification}, ministry["ministryrequestid"], 'ministryrequest', notificationtype, userid) else: - response = notificationservice().createnotification({"message" : notification}, requestid, requesttype, "State", userid) + response = notificationservice().createnotification({"message" : notification}, requestid, requesttype, notificationtype, userid) if _notificationtype == "Group Members": notification = self.__preparegroupmembernotification(state, requestid) - groupmemberresponse = notificationservice().createnotification({"message" : notification}, requestid, requesttype, _notificationtype, userid) + groupmemberresponse = notificationservice().createnotification({"message" : notification}, requestid, requesttype, notificationtype, userid) if response.success == True and groupmemberresponse.success == True : return DefaultMethodResult(True,'Notification added',requestid) else: diff --git a/request-management-api/request_api/services/eventservice.py b/request-management-api/request_api/services/eventservice.py index 4f22536b5..013977901 100644 --- a/request-management-api/request_api/services/eventservice.py +++ b/request-management-api/request_api/services/eventservice.py @@ -58,32 +58,11 @@ def posteventforaxisextension(self, ministryrequestid, extensionids, userid, use def postreminderevent(self): try: - start_time = timer.time() cfreventresponse = cfrdateevent().createdueevent() - cfreventresponse_time = timer.time() - print("--- CFR Event Response Time %s seconds ---" % (cfreventresponse_time - start_time)) - print(f"cfreventresponse = {cfreventresponse.success}") - legislativeeventresponse = legislativedateevent().createdueevent() - legislativeeventresponse_time = timer.time() - print("--- Legislative Event Response Time %s seconds ---" % (legislativeeventresponse_time - cfreventresponse_time)) - print(f"legislativeeventresponse = {legislativeeventresponse.success}") - divisioneventresponse = divisiondateevent().createdueevent() - divisioneventresponse_time = timer.time() - print("--- Division Event Response Time %s seconds ---" % (divisioneventresponse_time - legislativeeventresponse_time)) - print(f"divisioneventresponse = {divisioneventresponse.success}") - paymentremindereventresponse = paymentevent().createpaymentreminderevent() - paymentremindereventresponse_time = timer.time() - print("--- Payment Reminder Event Response Time %s seconds ---" % (paymentremindereventresponse_time - divisioneventresponse_time)) - print(f"paymentremindereventresponse = {paymentremindereventresponse.success}") - section5pendingresponse = section5pendingevent().createdueevent() - section5pendingresponse_time = timer.time() - print("--- Section 5 Pending Event Response Time %s seconds ---" % (section5pendingresponse_time - paymentremindereventresponse_time)) - print(f"section5pendingresponse = {section5pendingresponse.success}") - if cfreventresponse.success == False or legislativeeventresponse.success == False or divisioneventresponse.success == False or paymentremindereventresponse.success == False or section5pendingresponse == False: current_app.logger.error("FOI Notification failed for reminder event response=%s ; legislative response=%s ; division response=%s ; payment response=%s ; section5pending response=%s" % (cfreventresponse.message, legislativeeventresponse.message, divisioneventresponse.message, paymentremindereventresponse.message, section5pendingresponse.message)) return DefaultMethodResult(False,'Due reminder notifications failed',cfreventresponse.identifier) diff --git a/request-management-api/request_api/services/notificationservice.py b/request-management-api/request_api/services/notificationservice.py index f3a873c7d..f1914947e 100644 --- a/request-management-api/request_api/services/notificationservice.py +++ b/request-management-api/request_api/services/notificationservice.py @@ -15,6 +15,7 @@ from request_api.models.FOIRawRequestNotificationUsers import FOIRawRequestNotificationUser from request_api.models.FOIRawRequestComments import FOIRawRequestComment from request_api.models.FOIRequestComments import FOIRequestComment +from request_api.models.NotificationTypes import NotificationType from request_api.models.default_method_result import DefaultMethodResult from datetime import datetime as datetime2 import os @@ -36,11 +37,12 @@ class notificationservice: def createnotification(self, message, requestid, requesttype, notificationtype, userid, iscleanup=True): foirequest = self.getrequest(requestid, requesttype) if iscleanup == True: - self.__cleanupnotifications(requesttype, notificationtype, foirequest) + self.__cleanupnotifications(requesttype, notificationtype['name'], foirequest) return self.__createnotification(message, requestid, requesttype, notificationtype, userid, foirequest) - def createusernotification(self, message, requestid, requesttype, notificationtype, notificationuser, userid): + def createusernotification(self, message, requestid, requesttype, notificationtypename, notificationuser, userid): foirequest = self.getrequest(requestid, requesttype) + notificationtype = NotificationType().getnotificationtypeid(notificationtypename) return self.__createnotification(message, requestid, requesttype, notificationtype, userid, foirequest, {"userid": notificationuser}) def createremindernotification(self, message, requestid, requesttype, notificationtype, userid): @@ -49,13 +51,15 @@ def createremindernotification(self, message, requestid, requesttype, notificati def createcommentnotification(self, message, comment, commenttype, requesttype, userid): requestid = comment["ministryrequestid"] if requesttype == "ministryrequest" else comment["requestid"] - foirequest = self.getrequest(requestid, requesttype) - return self.__createnotification(message, requestid, requesttype, commenttype, userid, foirequest, comment) + foirequest = self.getrequest(requestid, requesttype) + notificationtype = NotificationType().getnotificationtypeid(commenttype) + return self.__createnotification(message, requestid, requesttype, notificationtype, userid, foirequest, comment) def createwatchernotification(self, message, requesttype, watcher, userid): requestid = watcher["ministryrequestid"] if requesttype == "ministryrequest" else watcher["requestid"] - foirequest = self.getrequest(requestid, requesttype) - return self.__createnotification(message, requestid, requesttype, 'Watcher', userid, foirequest, watcher) + foirequest = self.getrequest(requestid, requesttype) + notificationtype = NotificationType().getnotificationtypeid('Watcher') + return self.__createnotification(message, requestid, requesttype, notificationtype, userid, foirequest, watcher) def editcommentnotification(self, message, comment, userid): notificationsusers = FOIRequestNotification.getcommentnotifications(comment['commentid']) @@ -96,11 +100,11 @@ def dismissnotificationbyid(self, requesttype, notificationids): return self.__deletenotificationids(requesttype, notificationids) def dismissremindernotification(self, requesttype, notificationtype): - notificationid = notificationconfig().getnotificationtypelabel(notificationtype) + notificationlabel = notificationconfig().getnotificationtypelabel(notificationtype) if requesttype == "ministryrequest": - _ids = FOIRequestNotification.getnotificationidsbytype(notificationid) + _ids = FOIRequestNotification.getnotificationidsbytype(notificationlabel) else: - _ids = FOIRawRequestNotification.getnotificationidsbytype(notificationid) + _ids = FOIRawRequestNotification.getnotificationidsbytype(notificationlabel) self.__deletenotificationids(requesttype, _ids) def dismissnotifications_by_requestid_type_userid(self, requestid, requesttype, notificationtype, userid): @@ -148,8 +152,8 @@ def __cleanupnotifications(self, requesttype, notificationtype, foirequest): def __getcleanupnotificationids(self, notificationtype): notificationtypelabels = [] - notificationid = notificationconfig().getnotificationtypelabel(notificationtype) - notificationtypelabels.append(notificationid) + notificationlabel = notificationconfig().getnotificationtypelabel(notificationtype) + notificationtypelabels.append(notificationlabel) if notificationtype == "State" or notificationtype.endswith("Assignment"): notificationtypelabels.append(notificationconfig().getnotificationtypelabel("Group Members")) return notificationtypelabels @@ -265,7 +269,7 @@ def __preparenotification(self, message, requesttype, notificationtype, userid, notification.foirequestid = foirequest["foirequest_id"] #mute notifications for ministry users - mutenotification = self.__mutenotification(requesttype, notificationtype, foirequest) + mutenotification = self.__mutenotification(requesttype, notificationtype['name'], foirequest) usergroupfromkeycloak = KeycloakAdminService().getmembersbygroupname(foirequest["assignedministrygroup"]) if usergroupfromkeycloak is not None and len(usergroupfromkeycloak) > 0: for user in usergroupfromkeycloak[0].get("members"): @@ -276,23 +280,15 @@ def __preparenotification(self, message, requesttype, notificationtype, userid, notification.idnumber ='U-00' + str(foirequest['requestid']) mutenotification = False - print("notificationtype", notificationtype) - # in notificationtype remove space and make lower case - notificationtype_format = notificationtype.replace(" ", "").lower() - print ("notificationtype_format", notificationtype_format) - if notificationtype_format not in notificationtypes_cache: - print('Notification type not found in enum.', notificationtype) - else: - print('Notification type found', notificationtype) - notification.notificationtypelabel = notificationtypes_cache[notificationtype_format]['notificationtypelabel'] - notification.notificationtypeid = notificationtypes_cache[notificationtype_format]['notificationtypeid'] + notification.notificationtypelabel = notificationtype['notificationtypelabel'] + notification.notificationtypeid = notificationtype['notificationtypeid'] notification.axisnumber = foirequest["axisrequestid"] notification.version = foirequest["version"] notification.createdby = userid notification.notification = message notification.isdeleted = False - notificationusers = notificationuser().getnotificationusers(notificationtype, requesttype, userid, foirequest, requestjson) + notificationusers = notificationuser().getnotificationusers(notificationtype['name'], requesttype, userid, foirequest, requestjson) users = [] for _notificationuser in notificationusers: users.append(self.__preparenotificationuser(requesttype, _notificationuser, userid, mutenotification, ministryusers)) From ef5d348136d69d56f068ca0746b0951c3aae9885 Mon Sep 17 00:00:00 2001 From: divyav-aot Date: Mon, 8 Jan 2024 19:18:35 -0500 Subject: [PATCH 191/238] fixed issue related to groupmember notification --- .../services/notifications/notificationconfig.py | 4 ++-- .../services/notifications/notificationuser.py | 12 ++++++------ .../request_api/services/notificationservice.py | 16 ++++++++-------- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/request-management-api/request_api/services/notifications/notificationconfig.py b/request-management-api/request_api/services/notifications/notificationconfig.py index 5801726d9..b6b771206 100644 --- a/request-management-api/request_api/services/notifications/notificationconfig.py +++ b/request-management-api/request_api/services/notifications/notificationconfig.py @@ -24,7 +24,7 @@ def getnotificationtypelabel(self, notificationtype): if notificationtype_format in notificationtypes_cache: return notificationtypes_cache[notificationtype_format]['notificationtypelabel'] else: - print("Notification type not found in cache. Fetching from DB", notificationtype) + print("Notification type not found in json. Fetching from DB", notificationtype) id = NotificationType().getnotificationtypeid(notificationtype) if id is not None: return id['notificationtypelabel'] @@ -44,7 +44,7 @@ def getnotificationusertypelabel(self, notificationusertype): if notificationusertype_format in notificationusertypes_cache: return notificationusertypes_cache[notificationusertype_format]['notificationusertypelabel'] else: - print("Notification user type not found in cache. Fetching from DB", notificationusertype) + print("Notification user type not found in json. Fetching from DB", notificationusertype) id = NotificationUserType().getnotificationusertypesid(notificationusertype) if id is not None: return id['notificationusertypelabel'] diff --git a/request-management-api/request_api/services/notifications/notificationuser.py b/request-management-api/request_api/services/notifications/notificationuser.py index ddfb0cbf3..5f810690a 100644 --- a/request-management-api/request_api/services/notifications/notificationuser.py +++ b/request-management-api/request_api/services/notifications/notificationuser.py @@ -67,14 +67,14 @@ def __getwatchers(self, notificationtype, foirequest, requesttype, requestjson=N def __getassignees(self, foirequest, requesttype, notificationtype, requestjson=None): notificationusers = [] - notificationtypelabel = notificationconfig().getnotificationusertypelabel("Assignee") + notificationusertypelabel = notificationconfig().getnotificationusertypelabel("Assignee") if notificationtype == 'User Assignment Removal': - notificationusers.append({"userid": requestjson['userid'], "usertype":notificationtypelabel}) + notificationusers.append({"userid": requestjson['userid'], "usertype":notificationusertypelabel}) else: if requesttype == "ministryrequest" and foirequest["assignedministryperson"] is not None and (notificationtype == 'Ministry Assignment' or 'Assignment' not in notificationtype): - notificationusers.append({"userid":foirequest["assignedministryperson"], "usertype":notificationtypelabel}) + notificationusers.append({"userid":foirequest["assignedministryperson"], "usertype":notificationusertypelabel}) if self.__isministryonly(notificationtype) == False and foirequest["assignedto"] is not None and foirequest["assignedto"] != '' and (notificationtype == 'IAO Assignment' or 'Assignment' not in notificationtype): - notificationusers.append({"userid":foirequest["assignedto"], "usertype":notificationtypelabel}) + notificationusers.append({"userid":foirequest["assignedto"], "usertype":notificationusertypelabel}) return notificationusers def __isministryonly(self, notificationtype): @@ -123,11 +123,11 @@ def __preparetaggeduser(self, data): def __getgroupmembers(self,groupid): notificationusers = [] - notificationtypelabel = notificationconfig().getnotificationtypelabel("Group Members") + notificationusertypelabel = notificationconfig().getnotificationusertypelabel("Group Members") usergroupfromkeycloak= KeycloakAdminService().getmembersbygroupname(groupid) if usergroupfromkeycloak is not None and len(usergroupfromkeycloak) > 0: for user in usergroupfromkeycloak[0].get("members"): - notificationusers.append({"userid":user["username"], "usertype":notificationtypelabel}) + notificationusers.append({"userid":user["username"], "usertype":notificationusertypelabel}) return notificationusers return [] \ No newline at end of file diff --git a/request-management-api/request_api/services/notificationservice.py b/request-management-api/request_api/services/notificationservice.py index f1914947e..1e2c91a13 100644 --- a/request-management-api/request_api/services/notificationservice.py +++ b/request-management-api/request_api/services/notificationservice.py @@ -198,11 +198,11 @@ def __dismissnotificationbyuser(self, userid): return DefaultMethodResult(False,'Unable to delete the notifications',userid) def __dismissnotificationbytype(self, userid, type): - typeid = notificationconfig().getnotificationusertypelabel(type) - requestnotificationids = self.__getdismissparentidsbyuserandtype("ministryrequest", userid, typeid) - requestnotification = FOIRequestNotificationUser.dismissnotificationbyuserandtype(userid, typeid) - rawnotificationids = self.__getdismissparentidsbyuserandtype("rawrequest", userid, typeid) - rawnotification = FOIRawRequestNotificationUser.dismissnotificationbyuserandtype(userid, typeid) + notificationusertypelabel = notificationconfig().getnotificationusertypelabel(type) + requestnotificationids = self.__getdismissparentidsbyuserandtype("ministryrequest", userid, notificationusertypelabel) + requestnotification = FOIRequestNotificationUser.dismissnotificationbyuserandtype(userid, notificationusertypelabel) + rawnotificationids = self.__getdismissparentidsbyuserandtype("rawrequest", userid, notificationusertypelabel) + rawnotification = FOIRawRequestNotificationUser.dismissnotificationbyuserandtype(userid, notificationusertypelabel) prequestnotification = FOIRequestNotification.dismissnotification(requestnotificationids) prawnotification = FOIRawRequestNotification.dismissnotification(rawnotificationids) if requestnotification.success == True and rawnotification.success == True and prequestnotification.success == True and prawnotification.success == True: @@ -243,11 +243,11 @@ def __getdismissparentidsbyuser(self, requesttype, userid): _notficationids = FOIRawRequestNotificationUser.getnotificationsbyuser(userid) return self.__filterdismissparentids(_notficationids) - def __getdismissparentidsbyuserandtype(self, requesttype, userid, typeid): + def __getdismissparentidsbyuserandtype(self, requesttype, userid, notificationusertypelabel): if requesttype == "ministryrequest": - _notficationids = FOIRequestNotificationUser.getnotificationsbyuserandtype(userid, typeid) + _notficationids = FOIRequestNotificationUser.getnotificationsbyuserandtype(userid, notificationusertypelabel) else: - _notficationids = FOIRawRequestNotificationUser.getnotificationsbyuserandtype(userid, typeid) + _notficationids = FOIRawRequestNotificationUser.getnotificationsbyuserandtype(userid, notificationusertypelabel) return self.__filterdismissparentids(_notficationids) def __filterdismissparentids(self,_notficationids): From 83816e5193b381503d7b44b7b9143afb60d3a859 Mon Sep 17 00:00:00 2001 From: Richard Qi Date: Mon, 8 Jan 2024 19:35:58 -0800 Subject: [PATCH 192/238] 1. get applicant history 2. get applicant requests --- .../models/FOIRequestApplicants.py | 312 +++++++++++++++++- .../request_api/resources/foiapplicant.py | 61 +++- .../request_api/services/applicantservice.py | 110 +++++- 3 files changed, 463 insertions(+), 20 deletions(-) diff --git a/request-management-api/request_api/models/FOIRequestApplicants.py b/request-management-api/request_api/models/FOIRequestApplicants.py index 080773792..149c6931f 100644 --- a/request-management-api/request_api/models/FOIRequestApplicants.py +++ b/request-management-api/request_api/models/FOIRequestApplicants.py @@ -9,6 +9,7 @@ from .FOIRequests import FOIRequest from .FOIRequestContactInformation import FOIRequestContactInformation from .FOIRequestPersonalAttributes import FOIRequestPersonalAttribute +from .FOIRequestStatus import FOIRequestStatus from sqlalchemy import and_, or_, func, case import uuid @@ -126,6 +127,8 @@ def getapplicantbyemail(cls, email): #generate query selectedcolumns = [ + FOIRequestApplicant.applicantprofileid.label('applicantprofileid'), + func.to_char(FOIRequestApplicantMapping.created_at, 'YYYY-MM-DD HH24:MI:SS').label('updatedat'), FOIRequestApplicant.foirequestapplicantid.label('foirequestapplicantid'), FOIRequestApplicant.firstname.label('firstname'), FOIRequestApplicant.middlename.label('middlename'), @@ -311,6 +314,8 @@ def getapplicantbyemail(cls, email): ).order_by(FOIRequest.foirequestid.desc()).subquery() query_aggregate = _session.query( + func.array_agg(subquery_all.c.applicantprofileid).label('applicantprofileid'), + func.array_agg(subquery_all.c.updatedat).label('updatedat'), subquery_all.c.foirequestapplicantid, func.array_agg(subquery_all.c.firstname).label('firstname'), func.array_agg(subquery_all.c.middlename).label('middlename'), @@ -378,6 +383,8 @@ def searchapplicant(cls, keywords): #generate query selectedcolumns = [ + FOIRequestApplicant.applicantprofileid.label('applicantprofileid'), + func.to_char(FOIRequestApplicantMapping.created_at, 'YYYY-MM-DD HH24:MI:SS').label('updatedat'), FOIRequestApplicant.foirequestapplicantid.label('foirequestapplicantid'), FOIRequestApplicant.firstname.label('firstname'), FOIRequestApplicant.middlename.label('middlename'), @@ -553,6 +560,8 @@ def searchapplicant(cls, keywords): ).order_by(FOIRequest.foirequestid.desc()).subquery() query_aggregate = _session.query( + func.array_agg(subquery_all.c.applicantprofileid).label('applicantprofileid'), + func.array_agg(subquery_all.c.updatedat).label('updatedat'), subquery_all.c.foirequestapplicantid, func.array_agg(subquery_all.c.firstname).label('firstname'), func.array_agg(subquery_all.c.middlename).label('middlename'), @@ -611,13 +620,312 @@ def getsearchfilters(cls, keywords, contactemail, contacthomephone, contactworkp return searchfilters + + # applicant history + @classmethod + def getapplicanthistory(cls, applicantid): + #for queue/dashboard + _session = db.session + + applicantprofile = aliased(FOIRequestApplicant) + + #aliase for getting contact info + contactemail = aliased(FOIRequestContactInformation) + contactaddress = aliased(FOIRequestContactInformation) + contactaddress2 = aliased(FOIRequestContactInformation) + contacthomephone = aliased(FOIRequestContactInformation) + contactworkphone = aliased(FOIRequestContactInformation) + contactworkphone2 = aliased(FOIRequestContactInformation) + contactmobilephone = aliased(FOIRequestContactInformation) + contactother = aliased(FOIRequestContactInformation) + + city = aliased(FOIRequestContactInformation) + province = aliased(FOIRequestContactInformation) + postal = aliased(FOIRequestContactInformation) + country = aliased(FOIRequestContactInformation) + + #aliase for getting personal attributes + personalemployeenumber = aliased(FOIRequestPersonalAttribute) + personalcorrectionnumber = aliased(FOIRequestPersonalAttribute) + personalhealthnumber = aliased(FOIRequestPersonalAttribute) + + #generate query + selectedcolumns = [ + applicantprofile.applicantprofileid.label('applicantprofileid'), + func.to_char(FOIRequestApplicantMapping.created_at, 'YYYY-MM-DD HH24:MI:SS').label('updatedat'), + FOIRequestApplicant.foirequestapplicantid.label('foirequestapplicantid'), + FOIRequestApplicant.firstname.label('firstname'), + FOIRequestApplicant.middlename.label('middlename'), + FOIRequestApplicant.lastname.label('lastname'), + FOIRequestApplicant.alsoknownas.label('alsoknownas'), + func.to_char(FOIRequestApplicant.dob, 'YYYY-MM-DD').label('dob'), + FOIRequestApplicant.businessname.label('businessname'), + FOIRequest.foirequestid.label('foirequestid'), + FOIRequest.version.label('foirequestversion'), + FOIRequest.requesttype.label('requesttype'), + ApplicantCategory.name.label('applicantcategory'), + contactemail.contactinformation.label('email'), + contactaddress.contactinformation.label('address'), + contactaddress2.contactinformation.label('address2'), + contacthomephone.contactinformation.label('homephone'), + contactworkphone.contactinformation.label('workphone'), + contactworkphone2.contactinformation.label('workphone2'), + contactmobilephone.contactinformation.label('mobilephone'), + contactother.contactinformation.label('othercontactinfo'), + city.contactinformation.label('city'), + province.contactinformation.label('province'), + postal.contactinformation.label('postal'), + country.contactinformation.label('country'), + personalemployeenumber.attributevalue.label('employeenumber'), + personalcorrectionnumber.attributevalue.label('correctionnumber'), + personalhealthnumber.attributevalue.label('phn') + ] + + query_all = _session.query( + *selectedcolumns + ).join( + applicantprofile, + or_( + and_( + applicantprofile.foirequestapplicantid == applicantid, + applicantprofile.applicantprofileid == FOIRequestApplicant.applicantprofileid + ), + and_( + FOIRequestApplicant.foirequestapplicantid == applicantid, + applicantprofile.applicantprofileid.is_(None) + ) + ) + ).join( + FOIRequestApplicantMapping, + and_( + FOIRequestApplicantMapping.requestortypeid == 1, + FOIRequestApplicantMapping.foirequestapplicantid == FOIRequestApplicant.foirequestapplicantid) + ).join( + FOIRequest, + and_( + FOIRequest.foirequestid == FOIRequestApplicantMapping.foirequest_id, + FOIRequest.version == FOIRequestApplicantMapping.foirequestversion_id) + ).join( + ApplicantCategory, + ApplicantCategory.applicantcategoryid == FOIRequest.applicantcategoryid + ).join( + contactemail, + and_( + contactemail.foirequest_id == FOIRequest.foirequestid, + contactemail.foirequestversion_id == FOIRequest.version, + contactemail.contacttypeid == 1), + ).join( + contactaddress, + and_( + contactaddress.foirequest_id == FOIRequest.foirequestid, + contactaddress.foirequestversion_id == FOIRequest.version, + contactaddress.contacttypeid == 2, + contactaddress.contactinformation is not None, + contactaddress.dataformat == 'address'), + isouter=True + ).join( + contactaddress2, + and_( + contactaddress2.foirequest_id == FOIRequest.foirequestid, + contactaddress2.foirequestversion_id == FOIRequest.version, + contactaddress2.contacttypeid == 2, + contactaddress2.contactinformation is not None, + contactaddress2.dataformat == 'addressSecondary'), + isouter=True + ).join( + contacthomephone, + and_( + contacthomephone.foirequest_id == FOIRequest.foirequestid, + contacthomephone.foirequestversion_id == FOIRequest.version, + contacthomephone.contacttypeid == 3, + contacthomephone.contactinformation is not None), + isouter=True + ).join( + contactworkphone, + and_( + contactworkphone.foirequest_id == FOIRequest.foirequestid, + contactworkphone.foirequestversion_id == FOIRequest.version, + contactworkphone.contacttypeid == 4, + contactworkphone.contactinformation is not None), + isouter=True + ).join( + contactworkphone2, + and_( + contactworkphone2.foirequest_id == FOIRequest.foirequestid, + contactworkphone2.foirequestversion_id == FOIRequest.version, + contactworkphone2.contacttypeid == 5, + contactworkphone2.contactinformation is not None), + isouter=True + ).join( + contactmobilephone, + and_( + contactmobilephone.foirequest_id == FOIRequest.foirequestid, + contactmobilephone.foirequestversion_id == FOIRequest.version, + contactmobilephone.contacttypeid == 6, + contactmobilephone.contactinformation is not None), + isouter=True + ).join( + contactother, + and_( + contactother.foirequest_id == FOIRequest.foirequestid, + contactother.foirequestversion_id == FOIRequest.version, + contactother.contacttypeid == 7, + contactother.contactinformation is not None), + isouter=True + ).join( + city, + and_( + city.foirequest_id == FOIRequest.foirequestid, + city.foirequestversion_id == FOIRequest.version, + city.contacttypeid == 2, + city.contactinformation is not None, + city.dataformat == 'city'), + isouter=True + ).join( + province, + and_( + province.foirequest_id == FOIRequest.foirequestid, + province.foirequestversion_id == FOIRequest.version, + province.contacttypeid == 2, + province.contactinformation is not None, + province.dataformat == 'province'), + isouter=True + ).join( + country, + and_( + country.foirequest_id == FOIRequest.foirequestid, + country.foirequestversion_id == FOIRequest.version, + country.contacttypeid == 2, + country.contactinformation is not None, + country.dataformat == 'country'), + isouter=True + ).join( + postal, + and_( + postal.foirequest_id == FOIRequest.foirequestid, + postal.foirequestversion_id == FOIRequest.version, + postal.contacttypeid == 2, + postal.contactinformation is not None, + postal.dataformat == 'postal'), + isouter=True + ).join( + personalemployeenumber, + and_( + personalemployeenumber.foirequest_id == FOIRequest.foirequestid, + personalemployeenumber.foirequestversion_id == FOIRequest.version, + personalemployeenumber.personalattributeid == 1, + personalemployeenumber.attributevalue is not None), + isouter=True + ).join( + personalcorrectionnumber, + and_( + personalcorrectionnumber.foirequest_id == FOIRequest.foirequestid, + personalcorrectionnumber.foirequestversion_id == FOIRequest.version, + personalcorrectionnumber.personalattributeid == 2, + personalcorrectionnumber.attributevalue is not None), + isouter=True + ).join( + personalhealthnumber, + and_( + personalhealthnumber.foirequest_id == FOIRequest.foirequestid, + personalhealthnumber.foirequestversion_id == FOIRequest.version, + personalhealthnumber.personalattributeid == 3, + personalhealthnumber.attributevalue is not None), + isouter=True + ).filter( + FOIRequest.isactive == True + ).order_by(FOIRequestApplicantMapping.created_at.desc()) + + # print("query_applicant_history", query_all) + + applicantprofile_schema = ApplicantProfileSchema(many=True) + return applicantprofile_schema.dump(query_all.all()) + + + # requests by applicant id + @classmethod + def getapplicantrequests(cls, applicantid): + from .FOIMinistryRequests import FOIMinistryRequest + + #for queue/dashboard + _session = db.session + + applicantprofile = aliased(FOIRequestApplicant) + + #max foirequest version + subquery_foirequest_maxversion = _session.query(FOIRequest.foirequestid, func.max(FOIRequest.version).label('max_version')).group_by(FOIRequest.foirequestid).subquery() + joincondition = [ + subquery_foirequest_maxversion.c.foirequestid == FOIRequest.foirequestid, + subquery_foirequest_maxversion.c.max_version == FOIRequest.version, + ] + + #generate query + selectedcolumns = [ + FOIRequestApplicant.applicantprofileid.label('applicantprofileid'), + FOIRequestApplicant.foirequestapplicantid.label('foirequestapplicantid'), + FOIMinistryRequest.axisrequestid, + FOIRequestStatus.name.label('requeststatus'), + func.to_char(FOIRequest.receiveddate, 'YYYY-MM-DD HH24:MI:SS').label('receiveddate'), + FOIMinistryRequest.description + ] + + query_all = _session.query( + *selectedcolumns + ).distinct( + FOIRequest.foirequestid + ).join( + applicantprofile, + or_( + and_( + applicantprofile.foirequestapplicantid == applicantid, + applicantprofile.applicantprofileid == FOIRequestApplicant.applicantprofileid + ), + and_( + FOIRequestApplicant.foirequestapplicantid == applicantid, + applicantprofile.applicantprofileid.is_(None) + ) + ) + ).join( + FOIRequestApplicantMapping, + and_( + FOIRequestApplicantMapping.requestortypeid == 1, + FOIRequestApplicantMapping.foirequestapplicantid == FOIRequestApplicant.foirequestapplicantid) + ).join( + FOIRequest, + and_( + FOIRequest.foirequestid == FOIRequestApplicantMapping.foirequest_id, + FOIRequest.version == FOIRequestApplicantMapping.foirequestversion_id, + FOIRequest.isactive == True) + ).join( + subquery_foirequest_maxversion, + and_(*joincondition) + ).join( + FOIMinistryRequest, + and_( + FOIMinistryRequest.foirequest_id == FOIRequest.foirequestid, + FOIMinistryRequest.isactive == True) + ).join( + FOIRequestStatus, + FOIRequestStatus.requeststatusid == FOIMinistryRequest.requeststatusid + ).order_by(FOIRequest.foirequestid.desc()) + + # print('query_all', query_all) + + applicantrequest_schema = ApplicantRequestSchema(many=True) + return applicantrequest_schema.dump(query_all.all()) + + class FOIRequestApplicantSchema(ma.Schema): class Meta: fields = ('foirequestapplicantid','firstname','middlename','lastname','alsoknownas','dob','businessname') class ApplicantProfileSchema(ma.Schema): class Meta: - fields = ('foirequestapplicantid','firstname','middlename','lastname','alsoknownas','dob', - 'businessname','foirequestid','foirequestversion','requesttype','applicantcategory', + fields = ('applicantprofileid','updatedat','foirequestapplicantid','firstname','middlename','lastname', + 'alsoknownas','dob','businessname','foirequestid','foirequestversion','requesttype','applicantcategory', 'email','address','city','province','postal','country','homephone','workphone', 'workphone2','mobilephone','othercontactinfo','employeenumber','correctionnumber','phn') + +class ApplicantRequestSchema(ma.Schema): + class Meta: + fields = ('applicantprofileid','foirequestapplicantid','axisrequestid','requeststatus','receiveddate','description') \ No newline at end of file diff --git a/request-management-api/request_api/resources/foiapplicant.py b/request-management-api/request_api/resources/foiapplicant.py index 9f039e5f3..d7b62084a 100644 --- a/request-management-api/request_api/resources/foiapplicant.py +++ b/request-management-api/request_api/resources/foiapplicant.py @@ -88,7 +88,8 @@ def post(): return {'status': False, 'message':EXCEPTION_MESSAGE_NOT_FOUND}, 404 except BusinessException as exception: return {'status': exception.status_code, 'message':exception.message}, 500 - + + @cors_preflight('POST,OPTIONS') @API.route('/foiapplicants/save') class EventPagination(Resource): @@ -110,23 +111,51 @@ def post(): return {'status': False, 'message':EXCEPTION_MESSAGE_NOT_FOUND}, 404 except BusinessException as exception: return {'status': exception.status_code, 'message':exception.message}, 500 - -@cors_preflight('POST,OPTIONS') -@API.route('/foiapplicants/testsave') -class EventPagination(Resource): - """ Saves applicant info and request specific contact info for all open requests associated to an applicant - """ + + +@cors_preflight('GET,OPTIONS') +@API.route('/foiapplicants/history/') +class FOIApplicants(Resource): + """Resource for retriving all FOI assignees.""" + @staticmethod @TRACER.trace() @cross_origin(origins=allowedorigins()) - @cors_preflight('POST,OPTIONS') - def post(): + @auth.require + @auth.isiao + @cors_preflight('GET,OPTIONS') + def get(applicantid=None): + if applicantid is None or applicantid == 0: + return {'status': False, 'message':EXCEPTION_MESSAGE_BAD_REQUEST}, 400 try: - applicant = FOIRequestApplicantSchema().load(request.get_json()) - result = applicantservice().saveapplicantinfo(applicant, AuthHelper.getuserid()) - if result.success: - return {'status': result.success, 'message':result.message,'id':result.identifier} , 200 + result = applicantservice().getapplicanthistory(applicantid) + if result is not None: + return json.dumps(result), 200 else: - return {'status': False, 'message':EXCEPTION_MESSAGE_NOT_FOUND}, 404 - except BusinessException as exception: - return {'status': exception.status_code, 'message':exception.message}, 500 \ No newline at end of file + return {'status': False, 'message':EXCEPTION_MESSAGE_NOT_FOUND}, 404 + except BusinessException as exception: + return {'status': exception.status_code, 'message':exception.message}, 500 + + +@cors_preflight('GET,OPTIONS') +@API.route('/foiapplicants/requests/') +class FOIApplicants(Resource): + """Resource for retriving all FOI assignees.""" + + @staticmethod + @TRACER.trace() + @cross_origin(origins=allowedorigins()) + @auth.require + @auth.isiao + @cors_preflight('GET,OPTIONS') + def get(applicantid=None): + if applicantid is None or applicantid == 0: + return {'status': False, 'message':EXCEPTION_MESSAGE_BAD_REQUEST}, 400 + try: + result = applicantservice().getapplicantrequests(applicantid) + if result is not None: + return json.dumps(result), 200 + else: + return {'status': False, 'message':EXCEPTION_MESSAGE_NOT_FOUND}, 404 + except BusinessException as exception: + return {'status': exception.status_code, 'message':exception.message}, 500 \ No newline at end of file diff --git a/request-management-api/request_api/services/applicantservice.py b/request-management-api/request_api/services/applicantservice.py index 5eb5985bf..c0f0a10a9 100644 --- a/request-management-api/request_api/services/applicantservice.py +++ b/request-management-api/request_api/services/applicantservice.py @@ -29,6 +29,7 @@ def getapplicantbyemail(self, email): def searchapplicant(self, keywords): applicantqueue = [] applicants = FOIRequestApplicant.searchapplicant(keywords) + print('applicants: ', applicants) if applicants is not None: for applicant in applicants: applicantqueue.append(self.__prepareapplicant(applicant)) @@ -85,7 +86,6 @@ def __prepareapplicant(self, applicant): #'createdat' : self.__formatedate(applicant["createdat)"], 'businessName': self.__first_not_null(applicant["businessname"]), # 'applicant': applicant["applicant"], - 'applicantVersion': applicant["applicantversion"], 'foirequestID': applicant["foirequestid"], 'foirequestVersion': applicant["foirequestversion"], 'requestType': applicant["requesttype"], @@ -104,4 +104,110 @@ def __prepareapplicant(self, applicant): 'publicServiceEmployeeNumber': self.__first_not_null(applicant["employeenumber"]), 'correctionalServiceNumber': self.__first_not_null(applicant["correctionnumber"]), } - \ No newline at end of file + + def getapplicanthistory(self, applicantid): + applicantqueue = [] + + # order by update date desc + applicants = FOIRequestApplicant.getapplicanthistory(applicantid) + print('applicants: ', applicants) + if applicants is not None: + newer = self.__prepareapplicantforcomparing(applicants[0]) + updatedat = applicants[0]['updatedat'] + for applicant in applicants: + cur = self.__prepareapplicantforcomparing(applicant) + if(cur != newer): + applicantqueue.append(self.__prepareapplicanthistory(applicant, updatedat)) + newer = cur + + updatedat = applicant['updatedat'] + + applicantqueue.append(self.__prepareapplicanthistory(applicant, updatedat)) + + return applicantqueue + + def __prepareapplicantforcomparing(self, applicant): + return { + 'alsoKnownAs': applicant["alsoknownas"], + 'birthDate': applicant["dob"], + 'personalHealthNumber': applicant["phn"], + # 'foiRequestApplicantID': applicant["foirequestapplicantid"], + # 'applicantProfileID': applicant["applicantprofileid"], + # 'updatedat': applicant['updatedat'], + 'firstName': applicant["firstname"], + 'middleName': applicant["middlename"], + 'lastName': applicant["lastname"], + 'businessName': applicant["businessname"], + # 'foirequestID': applicant["foirequestid"], + # 'foirequestVersion': applicant["foirequestversion"], + # 'requestType': applicant["requesttype"], + 'email': applicant["email"], + 'address': applicant["address"], + 'city': applicant["city"], + 'province': applicant["province"], + 'postal': applicant["postal"], + 'country': applicant["country"], + 'phonePrimary': applicant["homephone"], + 'workPhonePrimary': applicant["workphone"], + 'workPhoneSecondary': applicant["workphone2"], + 'phoneSecondary': applicant["mobilephone"], + 'otherContactInfo': applicant["othercontactinfo"], + 'publicServiceEmployeeNumber': applicant["employeenumber"], + 'correctionalServiceNumber': applicant["correctionnumber"], + } + + def __prepareapplicanthistory(self, applicant, updatedat): + return { + updatedat: { + 'additionalPersonalInfo': { + 'alsoKnownAs': applicant["alsoknownas"], + 'birthDate': applicant["dob"], + 'personalHealthNumber': applicant["phn"], + }, + 'foiRequestApplicantID': applicant["foirequestapplicantid"], + 'applicantProfileID': applicant["applicantprofileid"], + 'updatedat': applicant['updatedat'], + 'firstName': applicant["firstname"], + 'middleName': applicant["middlename"], + 'lastName': applicant["lastname"], + 'businessName': applicant["businessname"], + 'foirequestID': applicant["foirequestid"], + 'foirequestVersion': applicant["foirequestversion"], + 'requestType': applicant["requesttype"], + 'email': applicant["email"], + 'address': applicant["address"], + 'city': applicant["city"], + 'province': applicant["province"], + 'postal': applicant["postal"], + 'country': applicant["country"], + 'phonePrimary': applicant["homephone"], + 'workPhonePrimary': applicant["workphone"], + 'workPhoneSecondary': applicant["workphone2"], + 'phoneSecondary': applicant["mobilephone"], + 'otherContactInfo': applicant["othercontactinfo"], + 'publicServiceEmployeeNumber': applicant["employeenumber"], + 'correctionalServiceNumber': applicant["correctionnumber"], + } + } + + def getapplicantrequests(self, applicantid): + requestqueue = [] + + # order by update date desc + requests = FOIRequestApplicant.getapplicantrequests(applicantid) + print('requests: ', requests) + if requests is not None: + for request in requests: + requestqueue.append(self.__preparerequest(request)) + + return requestqueue + + def __preparerequest(self, request): + return { + 'applicantprofileid': request["applicantprofileid"], + 'foirequestapplicantid': request["foirequestapplicantid"], + 'axisrequestid': request["axisrequestid"], + 'requeststatus': request["requeststatus"], + 'receiveddate': request["receiveddate"], + 'description': request["description"], + } \ No newline at end of file From d6a974d8114373feb412edbc7215b8c9a57e0431 Mon Sep 17 00:00:00 2001 From: divyav-aot Date: Tue, 9 Jan 2024 11:26:49 -0500 Subject: [PATCH 193/238] removed logs --- .../request_api/services/recordservice.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/request-management-api/request_api/services/recordservice.py b/request-management-api/request_api/services/recordservice.py index eda12999a..45a11662a 100644 --- a/request-management-api/request_api/services/recordservice.py +++ b/request-management-api/request_api/services/recordservice.py @@ -218,12 +218,9 @@ def __triggerpdfstitchservice(self, requestid, ministryrequestid, message, useri "attributes": json.JSONEncoder().encode(message["attributes"]), "totalfilesize": message["totalfilesize"] } - print("final message >>>>>> ", streamobject) if message["totalfilesize"] > int(self.stitchinglargefilesizelimit) and self.pdfstitchstreamkey_largefiles: - print("pdfstitchstreamkey_largefiles = ", self.pdfstitchstreamkey_largefiles) return eventqueueservice().add(self.pdfstitchstreamkey_largefiles, streamobject) elif self.pdfstitchstreamkey: - print("pdfstitchstreamkey = ", self.pdfstitchstreamkey) return eventqueueservice().add(self.pdfstitchstreamkey, streamobject) else: print("pdfstitch stream key is missing. Message is not pushed to the stream.") @@ -249,8 +246,7 @@ def __bulkcreate(self, requestid, ministryrequestid, records, userid): if (dbresponse.success): #processingrecords = [{**record, **{"recordid": dbresponse.args[0][record['s3uripath']]['recordid']}} for record in records if not record['attributes'].get('incompatible', False)] processingrecords = [{**record, **{"recordid": dbresponse.args[0][record['s3uripath']]['recordid']}} for record in records] - - print(processingrecords) + # record all jobs before sending first redis stream message to avoid race condition jobids, err = self.makedocreviewerrequest('POST', '/api/jobstatus', { 'records': processingrecords, From deef574170fd255d0b9df297da5c42664fbf731b Mon Sep 17 00:00:00 2001 From: "sumathi.thirumani" Date: Wed, 10 Jan 2024 15:49:24 -0800 Subject: [PATCH 194/238] Changes to default isoipcreview as false. --- .../request_api/services/foirequest/requestservicegetter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/request-management-api/request_api/services/foirequest/requestservicegetter.py b/request-management-api/request_api/services/foirequest/requestservicegetter.py index 086c244d5..635007d45 100644 --- a/request-management-api/request_api/services/foirequest/requestservicegetter.py +++ b/request-management-api/request_api/services/foirequest/requestservicegetter.py @@ -168,7 +168,7 @@ def __preparebaseinfo(self,request,foiministryrequestid,requestministry,requestm 'assignedministryperson':requestministry["assignedministryperson"], 'selectedMinistries':[{'code':requestministry['programarea.bcgovcode'],'id':requestministry['foiministryrequestid'],'name':requestministry['programarea.name'],'selected':'true'}], 'divisions': self.getdivisions(requestministrydivisions), - 'isoipcreview': requestministry['isoipcreview'], + 'isoipcreview': requestministry['isoipcreview'] if (requestministry['isoipcreview'] not in (None, '') and requestministry['isoipcreview'] in (True, False)) else False, 'isreopened': self.hasreopened(foiministryrequestid), 'oipcdetails': self.getoipcdetails(foiministryrequestid, requestministry['version']), 'onholdTransitionDate': self.getonholdtransition(foiministryrequestid), From 5b8e4578d72352f49e254d57c233405181edb092 Mon Sep 17 00:00:00 2001 From: Richard Qi Date: Wed, 10 Jan 2024 15:53:32 -0800 Subject: [PATCH 195/238] bug fix: save request created new applicant --- .../foirequest/requestservicecreate.py | 42 ++++++++++--------- .../foirequest/requestservicegetter.py | 11 +++-- 2 files changed, 29 insertions(+), 24 deletions(-) diff --git a/request-management-api/request_api/services/foirequest/requestservicecreate.py b/request-management-api/request_api/services/foirequest/requestservicecreate.py index cec25115b..f1689010b 100644 --- a/request-management-api/request_api/services/foirequest/requestservicecreate.py +++ b/request-management-api/request_api/services/foirequest/requestservicecreate.py @@ -128,25 +128,27 @@ def __prepareapplicants(self, foirequestschema, userid): selfalsoknownas=None selfdob=None if foirequestschema.get("additionalPersonalInfo") is not None and foirequestschema.get('requeststatusid') == 1: - if foirequestschema.get('foiRequestApplicantID', None): - requestapplicant = FOIRequestApplicantMapping() - requestapplicant.foirequestapplicantid = foirequestschema['foiRequestApplicantID'] - requestapplicant.requestortypeid = RequestorType().getrequestortype("Self")["requestortypeid"] - requestapplicantarr.append(requestapplicant) - else: - applicantinfo = foirequestschema.get("additionalPersonalInfo") - selfdob = applicantinfo["birthDate"] if requestservicebuilder().isNotBlankorNone(foirequestschema,"birthDate","additionalPersonalInfo") else None - selfalsoknownas = applicantinfo["alsoKnownAs"] if requestservicebuilder().isNotBlankorNone(foirequestschema,"alsoKnownAs","additionalPersonalInfo") else None - requestapplicantarr.append( - requestservicebuilder().createapplicant(foirequestschema.get("firstName"), - foirequestschema.get("lastName"), - "Self", - userid, - foirequestschema.get("middleName"), - foirequestschema.get("businessName"), - selfalsoknownas, - selfdob) - ) + applicantinfo = foirequestschema.get("additionalPersonalInfo") + selfdob = applicantinfo["birthDate"] if requestservicebuilder().isNotBlankorNone(foirequestschema,"birthDate","additionalPersonalInfo") else None + selfalsoknownas = applicantinfo["alsoKnownAs"] if requestservicebuilder().isNotBlankorNone(foirequestschema,"alsoKnownAs","additionalPersonalInfo") else None + + # if foirequestschema.get('foiRequestApplicantID') is None and foirequestschema.get('requeststatusid') == 1: + if foirequestschema.get('foiRequestApplicantID') is not None: + requestapplicant = FOIRequestApplicantMapping() + requestapplicant.foirequestapplicantid = foirequestschema['foiRequestApplicantID'] + requestapplicant.requestortypeid = RequestorType().getrequestortype("Self")["requestortypeid"] + requestapplicantarr.append(requestapplicant) + else: + requestapplicantarr.append( + requestservicebuilder().createapplicant(foirequestschema.get("firstName"), + foirequestschema.get("lastName"), + "Self", + userid, + foirequestschema.get("middleName"), + foirequestschema.get("businessName"), + selfalsoknownas, + selfdob) + ) #Prepare additional applicants if foirequestschema.get("additionalPersonalInfo") is not None: @@ -172,7 +174,7 @@ def __prepareapplicants(self, foirequestschema, userid): None, self.__getkeyvalue(addlapplicantinfo,"anotherAlsoKnownAs"), self.__getkeyvalue(addlapplicantinfo,"anotherBirthDate") ) - ) + ) return requestapplicantarr def __disablewatchers(self, ministryid, requestschema, userid): diff --git a/request-management-api/request_api/services/foirequest/requestservicegetter.py b/request-management-api/request_api/services/foirequest/requestservicegetter.py index e5ae2c249..aea1580d4 100644 --- a/request-management-api/request_api/services/foirequest/requestservicegetter.py +++ b/request-management-api/request_api/services/foirequest/requestservicegetter.py @@ -45,9 +45,10 @@ def getrequest(self,foirequestid,foiministryrequestid): dobraw = applicant['foirequestapplicant.dob'] dob = parse(dobraw).strftime(self.__genericdateformat()) if dobraw is not None else '' alsoknownas = applicant['foirequestapplicant.alsoknownas'] + foirequestapplicantid = applicant['foirequestapplicant.foirequestapplicantid'] requestortypeid = applicant['requestortype.requestortypeid'] if requestortypeid == 1: - baserequestinfo.update(self.__prepareapplicant(firstname, middlename, lastname, businessname)) + baserequestinfo.update(self.__prepareapplicant(foirequestapplicantid, firstname, middlename, lastname, businessname)) additionalpersonalinfo.update(self.__prepareadditionalpersonalinfo(requestortypeid, firstname, middlename, lastname, dob, alsoknownas)) baserequestdetails, additionalpersonalinfodetails = self.preparepersonalattributes(foirequestid, request['version']) @@ -91,9 +92,10 @@ def getrequestdetailsforministry(self,foirequestid,foiministryrequestid, authmem lastname = applicant['foirequestapplicant.lastname'] dobraw = applicant['foirequestapplicant.dob'] dob = parse(dobraw).strftime(self.__genericdateformat()) if dobraw is not None else '' + foirequestapplicantid = applicant['foirequestapplicant.foirequestapplicantid'] requestortypeid = applicant['requestortype.requestortypeid'] if requestortypeid == 1: - baserequestinfo.update(self.__prepareapplicant(firstname, middlename, lastname)) + baserequestinfo.update(self.__prepareapplicant(foirequestapplicantid, firstname, middlename, lastname)) additionalpersonalinfo.update(self.__prepareadditionalpersonalinfo(requestortypeid, firstname, middlename, lastname, dob)) baserequestdetails, additionalpersonalinfodetails = self.preparepersonalattributes(foirequestid, request['version']) baserequestinfo.update(baserequestdetails) @@ -227,12 +229,13 @@ def getministryrequest(self, foiministryrequestid): def __genericdateformat(self): return '%Y-%m-%d' - def __prepareapplicant(self,firstname= None, middlename= None, lastname= None, businessname= None): + def __prepareapplicant(self, foirequestapplicantid=None, firstname= None, middlename= None, lastname= None, businessname= None): return { 'firstName': firstname, 'middleName': middlename, 'lastName': lastname, - 'businessName': businessname, + 'businessName': businessname, + 'foiRequestApplicantID': foirequestapplicantid } def __prepareadditionalpersonalinfo(self, requestortypeid, firstname= None, middlename= None, lastname= None, dob= None, alsoknownas= None): From 99492a207e147bc68c5400d3df15f0d8ec515909 Mon Sep 17 00:00:00 2001 From: Richard Qi Date: Wed, 10 Jan 2024 17:02:55 -0800 Subject: [PATCH 196/238] applicant history only return differences --- .../request_api/services/applicantservice.py | 71 +++++++++---------- 1 file changed, 34 insertions(+), 37 deletions(-) diff --git a/request-management-api/request_api/services/applicantservice.py b/request-management-api/request_api/services/applicantservice.py index c0f0a10a9..ed171bdf8 100644 --- a/request-management-api/request_api/services/applicantservice.py +++ b/request-management-api/request_api/services/applicantservice.py @@ -117,13 +117,10 @@ def getapplicanthistory(self, applicantid): for applicant in applicants: cur = self.__prepareapplicantforcomparing(applicant) if(cur != newer): - applicantqueue.append(self.__prepareapplicanthistory(applicant, updatedat)) + applicantqueue.append({ updatedat: dict(set(cur.items()) - set(newer.items())) }) newer = cur - updatedat = applicant['updatedat'] - applicantqueue.append(self.__prepareapplicanthistory(applicant, updatedat)) - return applicantqueue def __prepareapplicantforcomparing(self, applicant): @@ -156,39 +153,39 @@ def __prepareapplicantforcomparing(self, applicant): 'correctionalServiceNumber': applicant["correctionnumber"], } - def __prepareapplicanthistory(self, applicant, updatedat): - return { - updatedat: { - 'additionalPersonalInfo': { - 'alsoKnownAs': applicant["alsoknownas"], - 'birthDate': applicant["dob"], - 'personalHealthNumber': applicant["phn"], - }, - 'foiRequestApplicantID': applicant["foirequestapplicantid"], - 'applicantProfileID': applicant["applicantprofileid"], - 'updatedat': applicant['updatedat'], - 'firstName': applicant["firstname"], - 'middleName': applicant["middlename"], - 'lastName': applicant["lastname"], - 'businessName': applicant["businessname"], - 'foirequestID': applicant["foirequestid"], - 'foirequestVersion': applicant["foirequestversion"], - 'requestType': applicant["requesttype"], - 'email': applicant["email"], - 'address': applicant["address"], - 'city': applicant["city"], - 'province': applicant["province"], - 'postal': applicant["postal"], - 'country': applicant["country"], - 'phonePrimary': applicant["homephone"], - 'workPhonePrimary': applicant["workphone"], - 'workPhoneSecondary': applicant["workphone2"], - 'phoneSecondary': applicant["mobilephone"], - 'otherContactInfo': applicant["othercontactinfo"], - 'publicServiceEmployeeNumber': applicant["employeenumber"], - 'correctionalServiceNumber': applicant["correctionnumber"], - } - } + # def __prepareapplicanthistory(self, applicant, updatedat): + # return { + # updatedat: { + # 'additionalPersonalInfo': { + # 'alsoKnownAs': applicant["alsoknownas"], + # 'birthDate': applicant["dob"], + # 'personalHealthNumber': applicant["phn"], + # }, + # 'foiRequestApplicantID': applicant["foirequestapplicantid"], + # 'applicantProfileID': applicant["applicantprofileid"], + # 'updatedat': applicant['updatedat'], + # 'firstName': applicant["firstname"], + # 'middleName': applicant["middlename"], + # 'lastName': applicant["lastname"], + # 'businessName': applicant["businessname"], + # 'foirequestID': applicant["foirequestid"], + # 'foirequestVersion': applicant["foirequestversion"], + # 'requestType': applicant["requesttype"], + # 'email': applicant["email"], + # 'address': applicant["address"], + # 'city': applicant["city"], + # 'province': applicant["province"], + # 'postal': applicant["postal"], + # 'country': applicant["country"], + # 'phonePrimary': applicant["homephone"], + # 'workPhonePrimary': applicant["workphone"], + # 'workPhoneSecondary': applicant["workphone2"], + # 'phoneSecondary': applicant["mobilephone"], + # 'otherContactInfo': applicant["othercontactinfo"], + # 'publicServiceEmployeeNumber': applicant["employeenumber"], + # 'correctionalServiceNumber': applicant["correctionnumber"], + # } + # } def getapplicantrequests(self, applicantid): requestqueue = [] From 971eb7ae0c8ec1de2b3c445fc24c81f1596dd429 Mon Sep 17 00:00:00 2001 From: "sumathi.thirumani" Date: Thu, 11 Jan 2024 12:48:20 -0800 Subject: [PATCH 197/238] Notification type changes. --- .../common/notificationtypes.json | 68 +++---------------- .../common/notificationusertypes.json | 28 ++++---- .../common/notificationtypes.json | 68 +++---------------- .../common/notificationusertypes.json | 24 ------- .../request_api/services/events/oipc.py | 8 ++- .../services/events/oipcduedate.py | 5 +- 6 files changed, 42 insertions(+), 159 deletions(-) diff --git a/notification-manager/common/notificationtypes.json b/notification-manager/common/notificationtypes.json index 5c04ecec7..b111c5974 100644 --- a/notification-manager/common/notificationtypes.json +++ b/notification-manager/common/notificationtypes.json @@ -1,142 +1,90 @@ { "state": { - "notificationtypeid": 1, "name": "State", - "description": "State", - "active": true, "notificationtypelabel": "state" }, "division": { - "notificationtypeid": 2, "name": "Division", - "description": "Division", - "active": true, "notificationtypelabel": "division" }, "newusercomments": { - "notificationtypeid": 3, "name": "New User Comments", - "description": "New User Comments", - "active": true, "notificationtypelabel": "newusercomments" }, "extension": { - "notificationtypeid": 4, "name": "Extension", - "description": "Extension", - "active": true, "notificationtypelabel": "extension" }, "iaoassignment": { - "notificationtypeid": 5, "name": "IAO Assignment", - "description": "IAO Assignment", - "active": true, "notificationtypelabel": "iaoassignment" }, "ministryassignment": { - "notificationtypeid": 6, "name": "Ministry Assignment", - "description": "Ministry Assignment", - "active": true, "notificationtypelabel": "ministryassignment" }, "cfrduereminder": { - "notificationtypeid": 7, "name": "CFR Due Reminder", - "description": "CFR Due Reminder", - "active": true, "notificationtypelabel": "cfrduereminder" }, "legislativeduereminder": { - "notificationtypeid": 8, "name": "Legislative Due Reminder", - "description": "Legislative Due Reminder", - "active": true, "notificationtypelabel": "legislativeduereminder" }, "replyusercomments": { - "notificationtypeid": 9, "name": "Reply User Comments", - "description": "Reply User Comments", - "active": true, "notificationtypelabel": "replyusercomments" }, "taggedusercomments": { - "notificationtypeid": 10, "name": "Tagged User Comments", - "description": "Tagged User Comments", - "active": true, "notificationtypelabel": "taggedusercomments" }, "cfrfeeform": { - "notificationtypeid": 11, "name": "CFR Fee Form", - "description": "CFR Fee Form", - "active": true, "notificationtypelabel": "cfrfeeform" }, "groupmembers": { - "notificationtypeid": 12, "name": "Group Members", - "description": "Group Members", - "active": true, "notificationtypelabel": "groupmembers" }, "divisionduereminder": { - "notificationtypeid": 13, "name": "Division Due Reminder", - "description": "Division Due Reminder", - "active": true, "notificationtypelabel": "divisionduereminder" }, "watcher": { - "notificationtypeid": 14, "name": "Watcher", - "description": "Watcher", - "active": true, "notificationtypelabel": "watcher" }, "userassignmentremoval": { - "notificationtypeid": 15, "name": "User Assignment Removal", - "description": "User Assignment Removal", - "active": true, "notificationtypelabel": "userassignmentremoval" }, "emailfailure": { - "notificationtypeid": 16, "name": "Email Failure", - "description": "Email Failure", - "active": true, "notificationtypelabel": "emailfailure" }, "payment": { - "notificationtypeid": 17, "name": "Payment", - "description": "Payment", - "active": true, "notificationtypelabel": "payment" }, "records": { "notificationtypeid": 18, - "name": "Records", - "description": "Records", - "active": true, "notificationtypelabel": "records" }, "pdfstitch": { - "notificationtypeid": 19, "name": "PDFStitch", - "description": "PDFStitch", - "active": true, "notificationtypelabel": "pdfstitch" }, "section5pendingreminder": { - "notificationtypeid": 20, "name": "Section 5 Pending Reminder", - "description": "Section 5 Pending Reminder", - "active": true, "notificationtypelabel": "section5pendingreminder" + }, + "oipc": { + "name": "OIPC", + "notificationtypelabel": "oipc" + }, + "oipcduereminder": { + "name": "OIPC Due Reminder", + "notificationtypelabel": "oipcduereminder" } } diff --git a/notification-manager/common/notificationusertypes.json b/notification-manager/common/notificationusertypes.json index 0ea835c44..4311de447 100644 --- a/notification-manager/common/notificationusertypes.json +++ b/notification-manager/common/notificationusertypes.json @@ -1,30 +1,34 @@ { "watcher": { - "notificationusertypeid": 1, "name": "Watcher", - "description": "Watcher", - "isactive": true, "notificationusertypelabel": "watcher" }, "assignee": { - "notificationusertypeid": 2, "name": "Assignee", - "description": "Assignee", - "isactive": true, + "notificationusertypelabel": "assignee" + }, + "groupmembers": { + "name": "Group Members", + "notificationusertypelabel": "assignee" + }, + "groupmember": { + "name": "groupmembers", + "notificationusertypelabel": "assignee" + }, + "comment": { + "name": "Comment", "notificationusertypelabel": "assignee" }, "commentuser": { - "notificationusertypeid": 3, "name": "Comment User", - "description": "Comment User", - "isactive": true, + "notificationusertypelabel": "commentuser" + }, + "comment tagged user": { + "name": "comment tagged user", "notificationusertypelabel": "commentuser" }, "triggereduser": { - "notificationusertypeid": 4, "name": "Triggered User", - "description": "Triggered User", - "isactive": true, "notificationusertypelabel": "triggereduser" } } diff --git a/request-management-api/common/notificationtypes.json b/request-management-api/common/notificationtypes.json index 5c04ecec7..b111c5974 100644 --- a/request-management-api/common/notificationtypes.json +++ b/request-management-api/common/notificationtypes.json @@ -1,142 +1,90 @@ { "state": { - "notificationtypeid": 1, "name": "State", - "description": "State", - "active": true, "notificationtypelabel": "state" }, "division": { - "notificationtypeid": 2, "name": "Division", - "description": "Division", - "active": true, "notificationtypelabel": "division" }, "newusercomments": { - "notificationtypeid": 3, "name": "New User Comments", - "description": "New User Comments", - "active": true, "notificationtypelabel": "newusercomments" }, "extension": { - "notificationtypeid": 4, "name": "Extension", - "description": "Extension", - "active": true, "notificationtypelabel": "extension" }, "iaoassignment": { - "notificationtypeid": 5, "name": "IAO Assignment", - "description": "IAO Assignment", - "active": true, "notificationtypelabel": "iaoassignment" }, "ministryassignment": { - "notificationtypeid": 6, "name": "Ministry Assignment", - "description": "Ministry Assignment", - "active": true, "notificationtypelabel": "ministryassignment" }, "cfrduereminder": { - "notificationtypeid": 7, "name": "CFR Due Reminder", - "description": "CFR Due Reminder", - "active": true, "notificationtypelabel": "cfrduereminder" }, "legislativeduereminder": { - "notificationtypeid": 8, "name": "Legislative Due Reminder", - "description": "Legislative Due Reminder", - "active": true, "notificationtypelabel": "legislativeduereminder" }, "replyusercomments": { - "notificationtypeid": 9, "name": "Reply User Comments", - "description": "Reply User Comments", - "active": true, "notificationtypelabel": "replyusercomments" }, "taggedusercomments": { - "notificationtypeid": 10, "name": "Tagged User Comments", - "description": "Tagged User Comments", - "active": true, "notificationtypelabel": "taggedusercomments" }, "cfrfeeform": { - "notificationtypeid": 11, "name": "CFR Fee Form", - "description": "CFR Fee Form", - "active": true, "notificationtypelabel": "cfrfeeform" }, "groupmembers": { - "notificationtypeid": 12, "name": "Group Members", - "description": "Group Members", - "active": true, "notificationtypelabel": "groupmembers" }, "divisionduereminder": { - "notificationtypeid": 13, "name": "Division Due Reminder", - "description": "Division Due Reminder", - "active": true, "notificationtypelabel": "divisionduereminder" }, "watcher": { - "notificationtypeid": 14, "name": "Watcher", - "description": "Watcher", - "active": true, "notificationtypelabel": "watcher" }, "userassignmentremoval": { - "notificationtypeid": 15, "name": "User Assignment Removal", - "description": "User Assignment Removal", - "active": true, "notificationtypelabel": "userassignmentremoval" }, "emailfailure": { - "notificationtypeid": 16, "name": "Email Failure", - "description": "Email Failure", - "active": true, "notificationtypelabel": "emailfailure" }, "payment": { - "notificationtypeid": 17, "name": "Payment", - "description": "Payment", - "active": true, "notificationtypelabel": "payment" }, "records": { "notificationtypeid": 18, - "name": "Records", - "description": "Records", - "active": true, "notificationtypelabel": "records" }, "pdfstitch": { - "notificationtypeid": 19, "name": "PDFStitch", - "description": "PDFStitch", - "active": true, "notificationtypelabel": "pdfstitch" }, "section5pendingreminder": { - "notificationtypeid": 20, "name": "Section 5 Pending Reminder", - "description": "Section 5 Pending Reminder", - "active": true, "notificationtypelabel": "section5pendingreminder" + }, + "oipc": { + "name": "OIPC", + "notificationtypelabel": "oipc" + }, + "oipcduereminder": { + "name": "OIPC Due Reminder", + "notificationtypelabel": "oipcduereminder" } } diff --git a/request-management-api/common/notificationusertypes.json b/request-management-api/common/notificationusertypes.json index 1048cc990..4311de447 100644 --- a/request-management-api/common/notificationusertypes.json +++ b/request-management-api/common/notificationusertypes.json @@ -1,58 +1,34 @@ { "watcher": { - "notificationusertypeid": 1, "name": "Watcher", - "description": "Watcher", - "isactive": true, "notificationusertypelabel": "watcher" }, "assignee": { - "notificationusertypeid": 2, "name": "Assignee", - "description": "Assignee", - "isactive": true, "notificationusertypelabel": "assignee" }, "groupmembers": { - "notificationusertypeid": 2, "name": "Group Members", - "description": "Assignee", - "isactive": true, "notificationusertypelabel": "assignee" }, "groupmember": { - "notificationusertypeid": 2, "name": "groupmembers", - "description": "Assignee", - "isactive": true, "notificationusertypelabel": "assignee" }, "comment": { - "notificationusertypeid": 2, "name": "Comment", - "description": "Assignee", - "isactive": true, "notificationusertypelabel": "assignee" }, "commentuser": { - "notificationusertypeid": 3, "name": "Comment User", - "description": "Comment User", - "isactive": true, "notificationusertypelabel": "commentuser" }, "comment tagged user": { - "notificationusertypeid": 3, "name": "comment tagged user", - "description": "Comment User", - "isactive": true, "notificationusertypelabel": "commentuser" }, "triggereduser": { - "notificationusertypeid": 4, "name": "Triggered User", - "description": "Triggered User", - "isactive": true, "notificationusertypelabel": "triggereduser" } } diff --git a/request-management-api/request_api/services/events/oipc.py b/request-management-api/request_api/services/events/oipc.py index 7899bb2d9..15b9b22ce 100644 --- a/request-management-api/request_api/services/events/oipc.py +++ b/request-management-api/request_api/services/events/oipc.py @@ -12,6 +12,7 @@ from request_api.exceptions import BusinessException from dateutil.parser import parse from request_api.utils.enums import CommentType +from request_api.models.NotificationTypes import NotificationType class oipcevent: """ FOI OIPC Event management service @@ -39,7 +40,8 @@ def __createcomment(self, requestid, oipc, userid): commentservice().createministryrequestcomment(comment, userid, CommentType.SystemGenerated.value) def __createnotification(self, requestid, oipc, userid): - return notificationservice().createnotification({"message" : self.__preparemessage(oipc)}, requestid, "ministryrequest", "OIPC", userid, False) + notificationtype = NotificationType().getnotificationtypeid(self.__notificationtype()) + return notificationservice().createnotification({"message" : self.__preparemessage(oipc)}, requestid, "ministryrequest", notificationtype, userid, False) def __maintained(self,coipcs, poipcs, inquiryoutcomes): @@ -146,7 +148,9 @@ def __preparemessage(self, oipc): return _inquirychange_msg elif oipc['event'] == EventType.inquiryoutcome.value: return 'OIPC '+ oipc['reviewtype'] +' Inquiry Decision: '+ oipc['inquiryoutcome'] - + + def __notificationtype(self): + return "OIPC" class EventType(Enum): add = "add" diff --git a/request-management-api/request_api/services/events/oipcduedate.py b/request-management-api/request_api/services/events/oipcduedate.py index 88fbd51b2..a8db3021a 100644 --- a/request-management-api/request_api/services/events/oipcduedate.py +++ b/request-management-api/request_api/services/events/oipcduedate.py @@ -5,6 +5,7 @@ from request_api.services.commons.duecalculator import duecalculator from request_api.services.notificationservice import notificationservice from request_api.models.FOIMinistryRequests import FOIMinistryRequest +from request_api.models.NotificationTypes import NotificationType import json from request_api.models.default_method_result import DefaultMethodResult from request_api.exceptions import BusinessException @@ -14,6 +15,7 @@ class oipcduedateevent(duecalculator): """ FOI OIPC Due Date Event management service """ + def createdueevent(self): try: @@ -39,7 +41,8 @@ def createdueevent(self): def __createnotification(self, message, requestid): if message is not None: - return notificationservice().createnotification({"message" : message}, requestid, "ministryrequest", self.__notificationtype(), self.__defaultuserid(), False) + notificationtype = NotificationType().getnotificationtypeid(self.__notificationtype()) + return notificationservice().createnotification({"message" : message}, requestid, "ministryrequest", notificationtype, self.__defaultuserid(), False) def __createcomment(self, entry, message): if message is not None: From 2e84083cd138e10919adf503b795b7d4d2f9e762 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 11 Jan 2024 15:36:32 -0800 Subject: [PATCH 198/238] integrating history and request endpoints for applicant profile --- .../FOI/FOIRequest/ApplicantProfileModal.js | 45 ++++++++++++------- .../models/FOIRequestApplicants.py | 4 +- .../request_api/services/applicantservice.py | 45 ++++++++++--------- 3 files changed, 55 insertions(+), 39 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js b/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js index cf3c4671b..12f56d682 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js @@ -16,7 +16,7 @@ import SearchIcon from "@material-ui/icons/Search"; import InputAdornment from "@mui/material/InputAdornment"; import InputBase from "@mui/material/InputBase"; import Grid from "@mui/material/Grid"; -import { fetchPotentialApplicants, fetchApplicantInfo, fetchApplicantContactHistory, saveApplicantInfo, fetchApplicantProfileByKeyword } from "../../../apiManager/services/FOI/foiApplicantProfileService"; +import { fetchPotentialApplicants, fetchApplicantInfo, fetchApplicantContactHistory, saveApplicantInfo, fetchApplicantProfileByKeyword, fetchApplicantRequests } from "../../../apiManager/services/FOI/foiApplicantProfileService"; import AddressContactDetails from "./AddressContanctInfo"; import ApplicantDetails from "./ApplicantDetails" import AdditionalApplicantDetails from "./AdditionalApplicantDetails"; @@ -104,24 +104,24 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { const requestHistoryColumns = [ { - field: "requestId", + field: "filenumber", headerName: "REQUEST ID", flex: 1, }, { - field: "currentState", + field: "requeststatus", headerName: "CURRENT STATE", flex: 1, }, { - field: "receivedDate", + field: "receiveddate", headerName: "RECEIVED DATE", flex: 1, }, { - field: "requestDescription", + field: "description", headerName: "REQUEST DESRCIPTION", - flex: 3, + flex: 2, }, ]; @@ -296,9 +296,9 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { } const showApplicantHistory = () => { - fetchApplicantContactHistory((err, res) => { + dispatch(fetchApplicantContactHistory(selectedApplicant.foiRequestApplicantID, (err, res) => { setApplicantHistory(res); - }) + })) } const back = () => { @@ -325,6 +325,17 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { } } + const toggleRequestHistory = () => { + if (!selectedApplicant.requestHistory) { + dispatch(fetchApplicantRequests(selectedApplicant.foiRequestApplicantID, (err, res) => { + setSelectedApplicant({...selectedApplicant, requestHistory: res}); + setShowRequestHistory(true) + })) + } else { + setShowRequestHistory(true) + } + } + return (
@@ -364,13 +375,13 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { orientation="vertical" /> setShowRequestHistory(true)} + onClick={toggleRequestHistory} disableRipple className={clsx("request-history-header applicant-profile-header", { [classes.disabledTitle]: !showRequestHistory })} > - Request History ({selectedApplicant.foirequestID.length}) + Request History ({selectedApplicant?.foirequestID?.length}) : @@ -391,7 +402,7 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { : (showRequestHistory ? <> - + { loading={isLoading} onRowClick={selectApplicantRow} getRowHeight={() => 'auto'} - getRowId={(row) => row.requestId} + getRowId={(row) => row.filenumber} /> : @@ -414,13 +425,15 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { aria-controls="panel1a-content" > {`APPLICANT CONTACT DETAILS`} - {entry.username} - {entry.date} + {entry.createdby} - {entry.updatedat}
-
- {entry.field}: {entry.value} -
+ {Object.keys(entry.fields).map((field) => +
+ {field}: {entry.fields[field]} +
+ )}
) diff --git a/request-management-api/request_api/models/FOIRequestApplicants.py b/request-management-api/request_api/models/FOIRequestApplicants.py index 149c6931f..928edae88 100644 --- a/request-management-api/request_api/models/FOIRequestApplicants.py +++ b/request-management-api/request_api/models/FOIRequestApplicants.py @@ -921,11 +921,11 @@ class Meta: class ApplicantProfileSchema(ma.Schema): class Meta: - fields = ('applicantprofileid','updatedat','foirequestapplicantid','firstname','middlename','lastname', + fields = ('applicantprofileid','updatedat','createdby','foirequestapplicantid','firstname','middlename','lastname', 'alsoknownas','dob','businessname','foirequestid','foirequestversion','requesttype','applicantcategory', 'email','address','city','province','postal','country','homephone','workphone', 'workphone2','mobilephone','othercontactinfo','employeenumber','correctionnumber','phn') class ApplicantRequestSchema(ma.Schema): class Meta: - fields = ('applicantprofileid','foirequestapplicantid','axisrequestid','requeststatus','receiveddate','description') \ No newline at end of file + fields = ('applicantprofileid','foirequestapplicantid','axisrequestid','filenumber', 'requeststatus','receiveddate','description') \ No newline at end of file diff --git a/request-management-api/request_api/services/applicantservice.py b/request-management-api/request_api/services/applicantservice.py index ed171bdf8..efb54f377 100644 --- a/request-management-api/request_api/services/applicantservice.py +++ b/request-management-api/request_api/services/applicantservice.py @@ -114,43 +114,45 @@ def getapplicanthistory(self, applicantid): if applicants is not None: newer = self.__prepareapplicantforcomparing(applicants[0]) updatedat = applicants[0]['updatedat'] + createdby = applicants[0]['createdby'] for applicant in applicants: cur = self.__prepareapplicantforcomparing(applicant) if(cur != newer): - applicantqueue.append({ updatedat: dict(set(cur.items()) - set(newer.items())) }) + applicantqueue.append({ "updatedat": updatedat, "createdby": createdby, "fields": dict(set(cur.items()) - set(newer.items()))}) newer = cur updatedat = applicant['updatedat'] + createdby = applicant['createdby'] return applicantqueue def __prepareapplicantforcomparing(self, applicant): return { - 'alsoKnownAs': applicant["alsoknownas"], - 'birthDate': applicant["dob"], - 'personalHealthNumber': applicant["phn"], + 'Also Known As': applicant["alsoknownas"], + 'Birth Date': applicant["dob"], + 'Personal Health Number': applicant["phn"], # 'foiRequestApplicantID': applicant["foirequestapplicantid"], # 'applicantProfileID': applicant["applicantprofileid"], # 'updatedat': applicant['updatedat'], - 'firstName': applicant["firstname"], - 'middleName': applicant["middlename"], - 'lastName': applicant["lastname"], - 'businessName': applicant["businessname"], + 'First Name': applicant["firstname"], + 'Middle Name': applicant["middlename"], + 'Last Name': applicant["lastname"], + 'Organization': applicant["businessname"], # 'foirequestID': applicant["foirequestid"], # 'foirequestVersion': applicant["foirequestversion"], # 'requestType': applicant["requesttype"], - 'email': applicant["email"], - 'address': applicant["address"], - 'city': applicant["city"], - 'province': applicant["province"], - 'postal': applicant["postal"], - 'country': applicant["country"], - 'phonePrimary': applicant["homephone"], - 'workPhonePrimary': applicant["workphone"], - 'workPhoneSecondary': applicant["workphone2"], - 'phoneSecondary': applicant["mobilephone"], - 'otherContactInfo': applicant["othercontactinfo"], - 'publicServiceEmployeeNumber': applicant["employeenumber"], - 'correctionalServiceNumber': applicant["correctionnumber"], + 'Email': applicant["email"], + 'Address': applicant["address"], + 'City': applicant["city"], + 'Province': applicant["province"], + 'Postal Code': applicant["postal"], + 'Country': applicant["country"], + 'Home Phone': applicant["homephone"], + 'Work Phone': applicant["workphone"], + 'Alternative Phone': applicant["workphone2"], + 'Mobile Phone': applicant["mobilephone"], + 'Other Contact Info': applicant["othercontactinfo"], + 'Employee Number': applicant["employeenumber"], + 'Corrections Number': applicant["correctionnumber"], } # def __prepareapplicanthistory(self, applicant, updatedat): @@ -204,6 +206,7 @@ def __preparerequest(self, request): 'applicantprofileid': request["applicantprofileid"], 'foirequestapplicantid': request["foirequestapplicantid"], 'axisrequestid': request["axisrequestid"], + 'filenumber': request["filenumber"], 'requeststatus': request["requeststatus"], 'receiveddate': request["receiveddate"], 'description': request["description"], From 9db77c2e7e09b561224f00c280e5b5a6e296e6dd Mon Sep 17 00:00:00 2001 From: Richard Qi Date: Thu, 11 Jan 2024 15:48:10 -0800 Subject: [PATCH 199/238] remove logs --- .../request_api/services/applicantservice.py | 44 ------------------- 1 file changed, 44 deletions(-) diff --git a/request-management-api/request_api/services/applicantservice.py b/request-management-api/request_api/services/applicantservice.py index ed171bdf8..beb9d3700 100644 --- a/request-management-api/request_api/services/applicantservice.py +++ b/request-management-api/request_api/services/applicantservice.py @@ -19,7 +19,6 @@ class applicantservice: def getapplicantbyemail(self, email): applicantqueue = [] applicants = FOIRequestApplicant.getapplicantbyemail(email) - print('applicants: ', applicants) if applicants is not None: for applicant in applicants: applicantqueue.append(self.__prepareapplicant(applicant)) @@ -29,7 +28,6 @@ def getapplicantbyemail(self, email): def searchapplicant(self, keywords): applicantqueue = [] applicants = FOIRequestApplicant.searchapplicant(keywords) - print('applicants: ', applicants) if applicants is not None: for applicant in applicants: applicantqueue.append(self.__prepareapplicant(applicant)) @@ -110,7 +108,6 @@ def getapplicanthistory(self, applicantid): # order by update date desc applicants = FOIRequestApplicant.getapplicanthistory(applicantid) - print('applicants: ', applicants) if applicants is not None: newer = self.__prepareapplicantforcomparing(applicants[0]) updatedat = applicants[0]['updatedat'] @@ -128,16 +125,10 @@ def __prepareapplicantforcomparing(self, applicant): 'alsoKnownAs': applicant["alsoknownas"], 'birthDate': applicant["dob"], 'personalHealthNumber': applicant["phn"], - # 'foiRequestApplicantID': applicant["foirequestapplicantid"], - # 'applicantProfileID': applicant["applicantprofileid"], - # 'updatedat': applicant['updatedat'], 'firstName': applicant["firstname"], 'middleName': applicant["middlename"], 'lastName': applicant["lastname"], 'businessName': applicant["businessname"], - # 'foirequestID': applicant["foirequestid"], - # 'foirequestVersion': applicant["foirequestversion"], - # 'requestType': applicant["requesttype"], 'email': applicant["email"], 'address': applicant["address"], 'city': applicant["city"], @@ -153,46 +144,11 @@ def __prepareapplicantforcomparing(self, applicant): 'correctionalServiceNumber': applicant["correctionnumber"], } - # def __prepareapplicanthistory(self, applicant, updatedat): - # return { - # updatedat: { - # 'additionalPersonalInfo': { - # 'alsoKnownAs': applicant["alsoknownas"], - # 'birthDate': applicant["dob"], - # 'personalHealthNumber': applicant["phn"], - # }, - # 'foiRequestApplicantID': applicant["foirequestapplicantid"], - # 'applicantProfileID': applicant["applicantprofileid"], - # 'updatedat': applicant['updatedat'], - # 'firstName': applicant["firstname"], - # 'middleName': applicant["middlename"], - # 'lastName': applicant["lastname"], - # 'businessName': applicant["businessname"], - # 'foirequestID': applicant["foirequestid"], - # 'foirequestVersion': applicant["foirequestversion"], - # 'requestType': applicant["requesttype"], - # 'email': applicant["email"], - # 'address': applicant["address"], - # 'city': applicant["city"], - # 'province': applicant["province"], - # 'postal': applicant["postal"], - # 'country': applicant["country"], - # 'phonePrimary': applicant["homephone"], - # 'workPhonePrimary': applicant["workphone"], - # 'workPhoneSecondary': applicant["workphone2"], - # 'phoneSecondary': applicant["mobilephone"], - # 'otherContactInfo': applicant["othercontactinfo"], - # 'publicServiceEmployeeNumber': applicant["employeenumber"], - # 'correctionalServiceNumber': applicant["correctionnumber"], - # } - # } - def getapplicantrequests(self, applicantid): requestqueue = [] # order by update date desc requests = FOIRequestApplicant.getapplicantrequests(applicantid) - print('requests: ', requests) if requests is not None: for request in requests: requestqueue.append(self.__preparerequest(request)) From e9cc806dcd7d62a96eb50fdb7e5c1ed80ae4a575 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 11 Jan 2024 15:36:32 -0800 Subject: [PATCH 200/238] integrating history and request endpoints for applicant profile --- .../FOI/foiApplicantProfileService.js | 60 ++++++++++++++++--- .../FOI/FOIRequest/ApplicantProfileModal.js | 45 +++++++++----- .../models/FOIRequestApplicants.py | 8 ++- .../request_api/services/applicantservice.py | 45 +++++++------- 4 files changed, 110 insertions(+), 48 deletions(-) diff --git a/forms-flow-web/src/apiManager/services/FOI/foiApplicantProfileService.js b/forms-flow-web/src/apiManager/services/FOI/foiApplicantProfileService.js index 6fbe6d932..f3ec2f7db 100644 --- a/forms-flow-web/src/apiManager/services/FOI/foiApplicantProfileService.js +++ b/forms-flow-web/src/apiManager/services/FOI/foiApplicantProfileService.js @@ -86,18 +86,62 @@ export const fetchApplicantInfo = async (firstname, ...rest) => { // }; }; -export const fetchApplicantContactHistory = (...rest) => { +export const fetchApplicantContactHistory = (applicantid, ...rest) => { + // const done = fnDone(rest); + // done(null, + // [{ + // field: "Email", + // value: "a@b.ca", + // date: "2023-12-11", + // username: "foiintake@idir", + // }] + // ); + const done = fnDone(rest); - done(null, - [{ - field: "Email", - value: "a@b.ca", - date: "2023-12-11", - username: "foiintake@idir", - }] + const apiUrl = replaceUrl( + API.FOI_GET_APPLICANT_HISTORY, + "", + applicantid ); + return (dispatch) => { + httpGETRequest(apiUrl, {}, UserService.getToken()) + .then((res) => { + if (res.data) { + done(null, res.data) + } else { + dispatch(serviceActionError(res)); + throw new Error(`Error in fetching potential applicants`) + } + }) + .catch((error) => { + catchError(error, dispatch); + }); + } } +export const fetchApplicantRequests = (applicantid, ...rest) => { + const done = fnDone(rest); + const apiUrl = replaceUrl( + API.FOI_GET_APPLICANT_REQUEST_HISTORY, + "", + applicantid + ); + return (dispatch) => { + httpGETRequest(apiUrl, {}, UserService.getToken()) + .then((res) => { + if (res.data) { + done(null, res.data) + } else { + dispatch(serviceActionError(res)); + throw new Error(`Error in fetching potential applicants`) + } + }) + .catch((error) => { + catchError(error, dispatch); + }); + } +}; + export const saveApplicantInfo = (applicant, ...rest) => { const done = fnDone(rest); const apiUrlgetRequestDetails = API.FOI_SAVE_REQUEST_APPLICANT_INFO; diff --git a/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js b/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js index cf3c4671b..12f56d682 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js @@ -16,7 +16,7 @@ import SearchIcon from "@material-ui/icons/Search"; import InputAdornment from "@mui/material/InputAdornment"; import InputBase from "@mui/material/InputBase"; import Grid from "@mui/material/Grid"; -import { fetchPotentialApplicants, fetchApplicantInfo, fetchApplicantContactHistory, saveApplicantInfo, fetchApplicantProfileByKeyword } from "../../../apiManager/services/FOI/foiApplicantProfileService"; +import { fetchPotentialApplicants, fetchApplicantInfo, fetchApplicantContactHistory, saveApplicantInfo, fetchApplicantProfileByKeyword, fetchApplicantRequests } from "../../../apiManager/services/FOI/foiApplicantProfileService"; import AddressContactDetails from "./AddressContanctInfo"; import ApplicantDetails from "./ApplicantDetails" import AdditionalApplicantDetails from "./AdditionalApplicantDetails"; @@ -104,24 +104,24 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { const requestHistoryColumns = [ { - field: "requestId", + field: "filenumber", headerName: "REQUEST ID", flex: 1, }, { - field: "currentState", + field: "requeststatus", headerName: "CURRENT STATE", flex: 1, }, { - field: "receivedDate", + field: "receiveddate", headerName: "RECEIVED DATE", flex: 1, }, { - field: "requestDescription", + field: "description", headerName: "REQUEST DESRCIPTION", - flex: 3, + flex: 2, }, ]; @@ -296,9 +296,9 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { } const showApplicantHistory = () => { - fetchApplicantContactHistory((err, res) => { + dispatch(fetchApplicantContactHistory(selectedApplicant.foiRequestApplicantID, (err, res) => { setApplicantHistory(res); - }) + })) } const back = () => { @@ -325,6 +325,17 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { } } + const toggleRequestHistory = () => { + if (!selectedApplicant.requestHistory) { + dispatch(fetchApplicantRequests(selectedApplicant.foiRequestApplicantID, (err, res) => { + setSelectedApplicant({...selectedApplicant, requestHistory: res}); + setShowRequestHistory(true) + })) + } else { + setShowRequestHistory(true) + } + } + return (
@@ -364,13 +375,13 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { orientation="vertical" /> setShowRequestHistory(true)} + onClick={toggleRequestHistory} disableRipple className={clsx("request-history-header applicant-profile-header", { [classes.disabledTitle]: !showRequestHistory })} > - Request History ({selectedApplicant.foirequestID.length}) + Request History ({selectedApplicant?.foirequestID?.length}) : @@ -391,7 +402,7 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { : (showRequestHistory ? <> - + { loading={isLoading} onRowClick={selectApplicantRow} getRowHeight={() => 'auto'} - getRowId={(row) => row.requestId} + getRowId={(row) => row.filenumber} /> : @@ -414,13 +425,15 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { aria-controls="panel1a-content" > {`APPLICANT CONTACT DETAILS`} - {entry.username} - {entry.date} + {entry.createdby} - {entry.updatedat}
-
- {entry.field}: {entry.value} -
+ {Object.keys(entry.fields).map((field) => +
+ {field}: {entry.fields[field]} +
+ )}
) diff --git a/request-management-api/request_api/models/FOIRequestApplicants.py b/request-management-api/request_api/models/FOIRequestApplicants.py index 149c6931f..25371fb52 100644 --- a/request-management-api/request_api/models/FOIRequestApplicants.py +++ b/request-management-api/request_api/models/FOIRequestApplicants.py @@ -663,6 +663,7 @@ def getapplicanthistory(cls, applicantid): FOIRequest.foirequestid.label('foirequestid'), FOIRequest.version.label('foirequestversion'), FOIRequest.requesttype.label('requesttype'), + FOIRequest.createdby.label('createdby'), ApplicantCategory.name.label('applicantcategory'), contactemail.contactinformation.label('email'), contactaddress.contactinformation.label('address'), @@ -864,8 +865,9 @@ def getapplicantrequests(cls, applicantid): FOIRequestApplicant.applicantprofileid.label('applicantprofileid'), FOIRequestApplicant.foirequestapplicantid.label('foirequestapplicantid'), FOIMinistryRequest.axisrequestid, + FOIMinistryRequest.filenumber, FOIRequestStatus.name.label('requeststatus'), - func.to_char(FOIRequest.receiveddate, 'YYYY-MM-DD HH24:MI:SS').label('receiveddate'), + func.to_char(FOIRequest.receiveddate, 'MON DD YYYY').label('receiveddate'), FOIMinistryRequest.description ] @@ -921,11 +923,11 @@ class Meta: class ApplicantProfileSchema(ma.Schema): class Meta: - fields = ('applicantprofileid','updatedat','foirequestapplicantid','firstname','middlename','lastname', + fields = ('applicantprofileid','updatedat','createdby','foirequestapplicantid','firstname','middlename','lastname', 'alsoknownas','dob','businessname','foirequestid','foirequestversion','requesttype','applicantcategory', 'email','address','city','province','postal','country','homephone','workphone', 'workphone2','mobilephone','othercontactinfo','employeenumber','correctionnumber','phn') class ApplicantRequestSchema(ma.Schema): class Meta: - fields = ('applicantprofileid','foirequestapplicantid','axisrequestid','requeststatus','receiveddate','description') \ No newline at end of file + fields = ('applicantprofileid','foirequestapplicantid','axisrequestid','filenumber', 'requeststatus','receiveddate','description') \ No newline at end of file diff --git a/request-management-api/request_api/services/applicantservice.py b/request-management-api/request_api/services/applicantservice.py index ed171bdf8..efb54f377 100644 --- a/request-management-api/request_api/services/applicantservice.py +++ b/request-management-api/request_api/services/applicantservice.py @@ -114,43 +114,45 @@ def getapplicanthistory(self, applicantid): if applicants is not None: newer = self.__prepareapplicantforcomparing(applicants[0]) updatedat = applicants[0]['updatedat'] + createdby = applicants[0]['createdby'] for applicant in applicants: cur = self.__prepareapplicantforcomparing(applicant) if(cur != newer): - applicantqueue.append({ updatedat: dict(set(cur.items()) - set(newer.items())) }) + applicantqueue.append({ "updatedat": updatedat, "createdby": createdby, "fields": dict(set(cur.items()) - set(newer.items()))}) newer = cur updatedat = applicant['updatedat'] + createdby = applicant['createdby'] return applicantqueue def __prepareapplicantforcomparing(self, applicant): return { - 'alsoKnownAs': applicant["alsoknownas"], - 'birthDate': applicant["dob"], - 'personalHealthNumber': applicant["phn"], + 'Also Known As': applicant["alsoknownas"], + 'Birth Date': applicant["dob"], + 'Personal Health Number': applicant["phn"], # 'foiRequestApplicantID': applicant["foirequestapplicantid"], # 'applicantProfileID': applicant["applicantprofileid"], # 'updatedat': applicant['updatedat'], - 'firstName': applicant["firstname"], - 'middleName': applicant["middlename"], - 'lastName': applicant["lastname"], - 'businessName': applicant["businessname"], + 'First Name': applicant["firstname"], + 'Middle Name': applicant["middlename"], + 'Last Name': applicant["lastname"], + 'Organization': applicant["businessname"], # 'foirequestID': applicant["foirequestid"], # 'foirequestVersion': applicant["foirequestversion"], # 'requestType': applicant["requesttype"], - 'email': applicant["email"], - 'address': applicant["address"], - 'city': applicant["city"], - 'province': applicant["province"], - 'postal': applicant["postal"], - 'country': applicant["country"], - 'phonePrimary': applicant["homephone"], - 'workPhonePrimary': applicant["workphone"], - 'workPhoneSecondary': applicant["workphone2"], - 'phoneSecondary': applicant["mobilephone"], - 'otherContactInfo': applicant["othercontactinfo"], - 'publicServiceEmployeeNumber': applicant["employeenumber"], - 'correctionalServiceNumber': applicant["correctionnumber"], + 'Email': applicant["email"], + 'Address': applicant["address"], + 'City': applicant["city"], + 'Province': applicant["province"], + 'Postal Code': applicant["postal"], + 'Country': applicant["country"], + 'Home Phone': applicant["homephone"], + 'Work Phone': applicant["workphone"], + 'Alternative Phone': applicant["workphone2"], + 'Mobile Phone': applicant["mobilephone"], + 'Other Contact Info': applicant["othercontactinfo"], + 'Employee Number': applicant["employeenumber"], + 'Corrections Number': applicant["correctionnumber"], } # def __prepareapplicanthistory(self, applicant, updatedat): @@ -204,6 +206,7 @@ def __preparerequest(self, request): 'applicantprofileid': request["applicantprofileid"], 'foirequestapplicantid': request["foirequestapplicantid"], 'axisrequestid': request["axisrequestid"], + 'filenumber': request["filenumber"], 'requeststatus': request["requeststatus"], 'receiveddate': request["receiveddate"], 'description': request["description"], From 89c354f129319c76160c03e776d8bb32313b5258 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 12 Jan 2024 11:43:56 -0800 Subject: [PATCH 201/238] fetch applicant by id for open state onwards minor integration fixes --- .../src/apiManager/endpoints/index.js | 3 + .../FOI/foiApplicantProfileService.js | 57 ++-- .../FOI/FOIRequest/ApplicantProfileModal.js | 27 +- .../models/FOIRequestApplicants.py | 259 ++++++++++++++++++ .../request_api/resources/foiapplicant.py | 23 ++ .../request_api/services/applicantservice.py | 6 + 6 files changed, 328 insertions(+), 47 deletions(-) diff --git a/forms-flow-web/src/apiManager/endpoints/index.js b/forms-flow-web/src/apiManager/endpoints/index.js index d13c7fd7b..b30abb030 100644 --- a/forms-flow-web/src/apiManager/endpoints/index.js +++ b/forms-flow-web/src/apiManager/endpoints/index.js @@ -42,6 +42,9 @@ const API = { FOI_GET_REQUEST_APPLICANTS: `${FOI_BASE_API_URL}/api/foiapplicants/`, FOI_SAVE_REQUEST_APPLICANT_INFO: `${FOI_BASE_API_URL}/api/foiapplicants/save`, FOI_REQUEST_APPLICANTS_SEARCH_KEYWORDS: `${FOI_BASE_API_URL}/api/foiapplicants/search`, + FOI_GET_APPLICANT_HISTORY: `${FOI_BASE_API_URL}/api/foiapplicants/history/`, + FOI_GET_APPLICANT_REQUEST_HISTORY: `${FOI_BASE_API_URL}/api/foiapplicants/requests/`, + FOI_GET_APPLICANT_INFO: `${FOI_BASE_API_URL}/api/foiapplicants/applicantid/`, FOI_GET_PROGRAMAREADIVISIONS: `${FOI_BASE_API_URL}/api/foiadmin/divisions`, FOI_POST_PROGRAMAREADIVISION: `${FOI_BASE_API_URL}/api/foiadmin/division`, diff --git a/forms-flow-web/src/apiManager/services/FOI/foiApplicantProfileService.js b/forms-flow-web/src/apiManager/services/FOI/foiApplicantProfileService.js index f3ec2f7db..9801e1024 100644 --- a/forms-flow-web/src/apiManager/services/FOI/foiApplicantProfileService.js +++ b/forms-flow-web/src/apiManager/services/FOI/foiApplicantProfileService.js @@ -50,40 +50,35 @@ export const fetchPotentialApplicants = (firstname, lastname, email, phone, ...r }; }; -export const fetchApplicantInfo = async (firstname, ...rest) => { +export const fetchApplicantInfo = (applicantid, ...rest) => { const done = fnDone(rest); - done(null, - { id: 1, lastName: 'Snow', firstName: 'Jon', age: 35, email: 'jon.snow@gmail.com', - additionalPersonalInfo: {birthDate: "2023-12-07"}, - requestHistory: [{requestId: "EDU-2023-234345", receivedDate: "2023-12-07", currentState: "Open", requestDescription: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but als"}] - } + // done(null, + // { id: 1, lastName: 'Snow', firstName: 'Jon', age: 35, email: 'jon.snow@gmail.com', + // additionalPersonalInfo: {birthDate: "2023-12-07"}, + // requestHistory: [{requestId: "EDU-2023-234345", receivedDate: "2023-12-07", currentState: "Open", requestDescription: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but als"}] + // } + // ); + // return; + const apiUrl = replaceUrl( + API.FOI_GET_APPLICANT_INFO, + "", + applicantid ); - return; - // const apiUrlgetRequestDetails = replaceUrl(replaceUrl( - // API.FOI_MINISTRYVIEW_REQUEST_API, - // "", - // requestId - // ), "", ministryId); - // return (dispatch) => { - // httpGETRequest(apiUrlgetRequestDetails, {}, UserService.getToken()) - // .then((res) => { - // if (res.data) { - // const foiRequest = res.data; - // dispatch(clearMinistryViewRequestDetails({})); - // dispatch(setFOIMinistryViewRequestDetail(foiRequest)); - // dispatch(fetchFOIMinistryAssignedToList(foiRequest.selectedMinistries[0].code.toLowerCase())); - // dispatch(setFOILoader(false)); - // } else { - // dispatch(serviceActionError(res)); - // dispatch(setFOILoader(false)); - // throw new Error(`Error in fetching ministry request details for request# ${requestId} ministry# ${ministryId}`) - // } - // }) - // .catch((error) => { - // catchError(error, dispatch); - // }); - // }; + return (dispatch) => { + httpGETRequest(apiUrl, {}, UserService.getToken()) + .then((res) => { + if (res.data) { + done(null, res.data) + } else { + dispatch(serviceActionError(res)); + throw new Error(`Error in fetching applicant info for applicant id # ${applicantid}`) + } + }) + .catch((error) => { + catchError(error, dispatch); + }); + }; }; export const fetchApplicantContactHistory = (applicantid, ...rest) => { diff --git a/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js b/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js index 12f56d682..7f058ff5f 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js @@ -139,9 +139,9 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { setIsLoading(false); })) } else { - fetchApplicantInfo(requestDetails.firstName, (err, res) => { + dispatch(fetchApplicantInfo(requestDetails.foiRequestApplicantID, (err, res) => { setSelectedApplicant(res); - }) + })) } } }, [modalOpen]) @@ -173,7 +173,10 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { } const selectApplicantRow = (e) => { - setSelectedApplicant(e.row); + dispatch(fetchApplicantRequests(e.row.foiRequestApplicantID, (err, res) => { + setSelectedApplicant({...e.row, requestHistory: res}); + setIsLoading(false); + })) } const handleClose = () => { @@ -304,8 +307,11 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { const back = () => { if (applicantHistory) { setApplicantHistory(false); + } else if (requestDetails.currentState === StateEnum.intakeinprogress.name) { + handleClose(); } else { setSelectedApplicant(false); + setShowRequestHistory(false); } } @@ -325,17 +331,6 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { } } - const toggleRequestHistory = () => { - if (!selectedApplicant.requestHistory) { - dispatch(fetchApplicantRequests(selectedApplicant.foiRequestApplicantID, (err, res) => { - setSelectedApplicant({...selectedApplicant, requestHistory: res}); - setShowRequestHistory(true) - })) - } else { - setShowRequestHistory(true) - } - } - return (
@@ -375,13 +370,13 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { orientation="vertical" /> setShowRequestHistory(true)} disableRipple className={clsx("request-history-header applicant-profile-header", { [classes.disabledTitle]: !showRequestHistory })} > - Request History ({selectedApplicant?.foirequestID?.length}) + Request History ({selectedApplicant?.requestHistory?.length}) : diff --git a/request-management-api/request_api/models/FOIRequestApplicants.py b/request-management-api/request_api/models/FOIRequestApplicants.py index 25371fb52..3c30b0269 100644 --- a/request-management-api/request_api/models/FOIRequestApplicants.py +++ b/request-management-api/request_api/models/FOIRequestApplicants.py @@ -90,6 +90,265 @@ def updateapplicantprofile(cls, foirequestapplicantid, firstname, lastname, midd else: return DefaultMethodResult(True,'No update',applicant.foirequestapplicantid) + # Search applicant by id + @classmethod + def getapplicantbyid(cls, applicantid): + from .FOIMinistryRequests import FOIMinistryRequest + + #for queue/dashboard + _session = db.session + + #aliase for getting contact info + contactemail = aliased(FOIRequestContactInformation) + contactaddress = aliased(FOIRequestContactInformation) + contactaddress2 = aliased(FOIRequestContactInformation) + contacthomephone = aliased(FOIRequestContactInformation) + contactworkphone = aliased(FOIRequestContactInformation) + contactworkphone2 = aliased(FOIRequestContactInformation) + contactmobilephone = aliased(FOIRequestContactInformation) + contactother = aliased(FOIRequestContactInformation) + + city = aliased(FOIRequestContactInformation) + province = aliased(FOIRequestContactInformation) + postal = aliased(FOIRequestContactInformation) + country = aliased(FOIRequestContactInformation) + + #aliase for getting personal attributes + personalemployeenumber = aliased(FOIRequestPersonalAttribute) + personalcorrectionnumber = aliased(FOIRequestPersonalAttribute) + personalhealthnumber = aliased(FOIRequestPersonalAttribute) + + #max foirequest version + subquery_foirequest_maxversion = _session.query(FOIRequest.foirequestid, func.max(FOIRequest.version).label('max_version')).group_by(FOIRequest.foirequestid).subquery() + joincondition = [ + subquery_foirequest_maxversion.c.foirequestid == FOIRequest.foirequestid, + subquery_foirequest_maxversion.c.max_version == FOIRequest.version, + ] + + #generate query + selectedcolumns = [ + FOIRequestApplicant.applicantprofileid.label('applicantprofileid'), + func.to_char(FOIRequestApplicantMapping.created_at, 'YYYY-MM-DD HH24:MI:SS').label('updatedat'), + FOIRequestApplicant.foirequestapplicantid.label('foirequestapplicantid'), + FOIRequestApplicant.firstname.label('firstname'), + FOIRequestApplicant.middlename.label('middlename'), + FOIRequestApplicant.lastname.label('lastname'), + FOIRequestApplicant.alsoknownas.label('alsoknownas'), + func.to_char(FOIRequestApplicant.dob, 'YYYY-MM-DD').label('dob'), + FOIRequestApplicant.businessname.label('businessname'), + FOIRequest.foirequestid.label('foirequestid'), + FOIRequest.version.label('foirequestversion'), + FOIRequest.requesttype.label('requesttype'), + ApplicantCategory.name.label('applicantcategory'), + contactemail.contactinformation.label('email'), + contactaddress.contactinformation.label('address'), + contactaddress2.contactinformation.label('address2'), + contacthomephone.contactinformation.label('homephone'), + contactworkphone.contactinformation.label('workphone'), + contactworkphone2.contactinformation.label('workphone2'), + contactmobilephone.contactinformation.label('mobilephone'), + contactother.contactinformation.label('othercontactinfo'), + city.contactinformation.label('city'), + province.contactinformation.label('province'), + postal.contactinformation.label('postal'), + country.contactinformation.label('country'), + personalemployeenumber.attributevalue.label('employeenumber'), + personalcorrectionnumber.attributevalue.label('correctionnumber'), + personalhealthnumber.attributevalue.label('phn') + ] + + subquery_all = _session.query( + *selectedcolumns + ).join( + FOIRequestApplicantMapping, + and_( + FOIRequestApplicantMapping.foirequest_id == FOIRequest.foirequestid, + FOIRequestApplicantMapping.foirequestversion_id == FOIRequest.version, + FOIRequestApplicantMapping.requestortypeid == 1), + ).join( + FOIRequestApplicant, + FOIRequestApplicant.foirequestapplicantid == FOIRequestApplicantMapping.foirequestapplicantid + # and_( + # FOIRequestApplicant.foirequestapplicantid == FOIRequestApplicantMapping.foirequestapplicantid, + # FOIRequestApplicant.isactive != False + # ) + ).join( + ApplicantCategory, + ApplicantCategory.applicantcategoryid == FOIRequest.applicantcategoryid + ).join( + subquery_foirequest_maxversion, + and_(*joincondition) + ).join( + FOIMinistryRequest, + and_( + FOIMinistryRequest.foirequest_id == FOIRequest.foirequestid, + FOIMinistryRequest.isactive == True) + ).join( + contactemail, + and_( + contactemail.foirequest_id == FOIRequest.foirequestid, + contactemail.foirequestversion_id == FOIRequest.version, + contactemail.contacttypeid == 1), + ).join( + contactaddress, + and_( + contactaddress.foirequest_id == FOIRequest.foirequestid, + contactaddress.foirequestversion_id == FOIRequest.version, + contactaddress.contacttypeid == 2, + contactaddress.contactinformation is not None, + contactaddress.dataformat == 'address'), + isouter=True + ).join( + contactaddress2, + and_( + contactaddress2.foirequest_id == FOIRequest.foirequestid, + contactaddress2.foirequestversion_id == FOIRequest.version, + contactaddress2.contacttypeid == 2, + contactaddress2.contactinformation is not None, + contactaddress2.dataformat == 'addressSecondary'), + isouter=True + ).join( + contacthomephone, + and_( + contacthomephone.foirequest_id == FOIRequest.foirequestid, + contacthomephone.foirequestversion_id == FOIRequest.version, + contacthomephone.contacttypeid == 3, + contacthomephone.contactinformation is not None), + isouter=True + ).join( + contactworkphone, + and_( + contactworkphone.foirequest_id == FOIRequest.foirequestid, + contactworkphone.foirequestversion_id == FOIRequest.version, + contactworkphone.contacttypeid == 4, + contactworkphone.contactinformation is not None), + isouter=True + ).join( + contactworkphone2, + and_( + contactworkphone2.foirequest_id == FOIRequest.foirequestid, + contactworkphone2.foirequestversion_id == FOIRequest.version, + contactworkphone2.contacttypeid == 5, + contactworkphone2.contactinformation is not None), + isouter=True + ).join( + contactmobilephone, + and_( + contactmobilephone.foirequest_id == FOIRequest.foirequestid, + contactmobilephone.foirequestversion_id == FOIRequest.version, + contactmobilephone.contacttypeid == 6, + contactmobilephone.contactinformation is not None), + isouter=True + ).join( + contactother, + and_( + contactother.foirequest_id == FOIRequest.foirequestid, + contactother.foirequestversion_id == FOIRequest.version, + contactother.contacttypeid == 7, + contactother.contactinformation is not None), + isouter=True + ).join( + city, + and_( + city.foirequest_id == FOIRequest.foirequestid, + city.foirequestversion_id == FOIRequest.version, + city.contacttypeid == 2, + city.contactinformation is not None, + city.dataformat == 'city'), + isouter=True + ).join( + province, + and_( + province.foirequest_id == FOIRequest.foirequestid, + province.foirequestversion_id == FOIRequest.version, + province.contacttypeid == 2, + province.contactinformation is not None, + province.dataformat == 'province'), + isouter=True + ).join( + country, + and_( + country.foirequest_id == FOIRequest.foirequestid, + country.foirequestversion_id == FOIRequest.version, + country.contacttypeid == 2, + country.contactinformation is not None, + country.dataformat == 'country'), + isouter=True + ).join( + postal, + and_( + postal.foirequest_id == FOIRequest.foirequestid, + postal.foirequestversion_id == FOIRequest.version, + postal.contacttypeid == 2, + postal.contactinformation is not None, + postal.dataformat == 'postal'), + isouter=True + ).join( + personalemployeenumber, + and_( + personalemployeenumber.foirequest_id == FOIRequest.foirequestid, + personalemployeenumber.foirequestversion_id == FOIRequest.version, + personalemployeenumber.personalattributeid == 1, + personalemployeenumber.attributevalue is not None), + isouter=True + ).join( + personalcorrectionnumber, + and_( + personalcorrectionnumber.foirequest_id == FOIRequest.foirequestid, + personalcorrectionnumber.foirequestversion_id == FOIRequest.version, + personalcorrectionnumber.personalattributeid == 2, + personalcorrectionnumber.attributevalue is not None), + isouter=True + ).join( + personalhealthnumber, + and_( + personalhealthnumber.foirequest_id == FOIRequest.foirequestid, + personalhealthnumber.foirequestversion_id == FOIRequest.version, + personalhealthnumber.personalattributeid == 3, + personalhealthnumber.attributevalue is not None), + isouter=True + ).filter( + # FOIMinistryRequest.requeststatusid != 3, + FOIRequest.isactive == True, + FOIRequestApplicant.foirequestapplicantid == applicantid + ).order_by(FOIRequest.foirequestid.desc()).subquery() + + query_aggregate = _session.query( + func.array_agg(subquery_all.c.applicantprofileid).label('applicantprofileid'), + func.array_agg(subquery_all.c.updatedat).label('updatedat'), + subquery_all.c.foirequestapplicantid, + func.array_agg(subquery_all.c.firstname).label('firstname'), + func.array_agg(subquery_all.c.middlename).label('middlename'), + func.array_agg(subquery_all.c.lastname).label('lastname'), + func.array_agg(subquery_all.c.alsoknownas).label('alsoknownas'), + func.array_agg(subquery_all.c.dob).label('dob'), + func.array_agg(subquery_all.c.businessname).label('businessname'), + func.array_agg(subquery_all.c.foirequestid).label('foirequestid'), + func.array_agg(subquery_all.c.foirequestversion).label('foirequestversion'), + func.array_agg(subquery_all.c.requesttype).label('requesttype'), + func.array_agg(subquery_all.c.applicantcategory).label('applicantcategory'), + func.array_agg(subquery_all.c.email).label('email'), + func.array_agg(subquery_all.c.address).label('address'), + func.array_agg(subquery_all.c.city).label('city'), + func.array_agg(subquery_all.c.province).label('province'), + func.array_agg(subquery_all.c.postal).label('postal'), + func.array_agg(subquery_all.c.country).label('country'), + func.array_agg(subquery_all.c.homephone).label('homephone'), + func.array_agg(subquery_all.c.workphone).label('workphone'), + func.array_agg(subquery_all.c.workphone2).label('workphone2'), + func.array_agg(subquery_all.c.mobilephone).label('mobilephone'), + func.array_agg(subquery_all.c.othercontactinfo).label('othercontactinfo'), + func.array_agg(subquery_all.c.employeenumber).label('employeenumber'), + func.array_agg(subquery_all.c.correctionnumber).label('correctionnumber'), + func.array_agg(subquery_all.c.phn).label('phn') + ).group_by(subquery_all.c.foirequestapplicantid) + + + print("query_by_id", query_aggregate) + + applicantprofile_schema = ApplicantProfileSchema() + return applicantprofile_schema.dump(query_aggregate.first()) + # Search applicant by email @classmethod def getapplicantbyemail(cls, email): diff --git a/request-management-api/request_api/resources/foiapplicant.py b/request-management-api/request_api/resources/foiapplicant.py index d7b62084a..a8ce90e33 100644 --- a/request-management-api/request_api/resources/foiapplicant.py +++ b/request-management-api/request_api/resources/foiapplicant.py @@ -157,5 +157,28 @@ def get(applicantid=None): return json.dumps(result), 200 else: return {'status': False, 'message':EXCEPTION_MESSAGE_NOT_FOUND}, 404 + except BusinessException as exception: + return {'status': exception.status_code, 'message':exception.message}, 500 + +@cors_preflight('GET,OPTIONS') +@API.route('/foiapplicants/applicantid/') +class FOIApplicants(Resource): + """Resource for retriving applicant by id""" + + @staticmethod + @TRACER.trace() + @cross_origin(origins=allowedorigins()) + @auth.require + @auth.isiao + @cors_preflight('GET,OPTIONS') + def get(applicantid=None): + if applicantid is None or applicantid == 0: + return {'status': False, 'message':EXCEPTION_MESSAGE_BAD_REQUEST}, 400 + try: + result = applicantservice().getapplicantbyid(applicantid) + if result is not None: + return json.dumps(result), 200 + else: + return {'status': False, 'message':EXCEPTION_MESSAGE_NOT_FOUND}, 404 except BusinessException as exception: return {'status': exception.status_code, 'message':exception.message}, 500 \ No newline at end of file diff --git a/request-management-api/request_api/services/applicantservice.py b/request-management-api/request_api/services/applicantservice.py index efb54f377..54f69c0ba 100644 --- a/request-management-api/request_api/services/applicantservice.py +++ b/request-management-api/request_api/services/applicantservice.py @@ -25,6 +25,12 @@ def getapplicantbyemail(self, email): applicantqueue.append(self.__prepareapplicant(applicant)) return applicantqueue + + def getapplicantbyid(self, applicantid): + applicant = FOIRequestApplicant.getapplicantbyid(applicantid) + applicant = self.__prepareapplicant(applicant) + applicant['requestHistory'] = self.getapplicantrequests(applicantid) + return applicant def searchapplicant(self, keywords): applicantqueue = [] From f022d659347f13a80a15f74c2ce3e5962a6cc3c8 Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Mon, 15 Jan 2024 11:28:51 -0800 Subject: [PATCH 202/238] Update replaceattachmenet message --- .../FOI/customComponents/Attachments/AttachmentModal.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/forms-flow-web/src/components/FOI/customComponents/Attachments/AttachmentModal.js b/forms-flow-web/src/components/FOI/customComponents/Attachments/AttachmentModal.js index 5ac12bd45..b250306fd 100644 --- a/forms-flow-web/src/components/FOI/customComponents/Attachments/AttachmentModal.js +++ b/forms-flow-web/src/components/FOI/customComponents/Attachments/AttachmentModal.js @@ -323,8 +323,8 @@ export default function AttachmentModal({ body: ( <> Replace the existing record with a reformatted or updated - version of the same record.

The original file that was - uploaded will still be available for download. + version of the same record.

If the file being replaced + is also a pdf file, the replaced file will no longer be available. ), }; From 1648013ed5058154834605fa9ca3a0e4b86e1a73 Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Mon, 15 Jan 2024 12:19:19 -0800 Subject: [PATCH 203/238] Handle .pdf mimetype --- .../components/FOI/customComponents/FileUpload/util.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/forms-flow-web/src/components/FOI/customComponents/FileUpload/util.js b/forms-flow-web/src/components/FOI/customComponents/FileUpload/util.js index dbc2c3831..026508ccd 100644 --- a/forms-flow-web/src/components/FOI/customComponents/FileUpload/util.js +++ b/forms-flow-web/src/components/FOI/customComponents/FileUpload/util.js @@ -35,8 +35,16 @@ export const getErrorMessage = (_duplicateFiles, _typeErrorFiles, _overSizedFile if (_overSizedFiles.length > 0) { _errorMessage.push(<>The specified file(s) {_overSizedFiles.join(", ")} could not be uploaded. Only files {maxFileSize}MB or under can be uploaded.); } + const hasOnlyPdfMimeTypes = (mimeTypes) => { + let result = true; + mimeTypes.forEach((mimeType) => { + if (mimeType !== 'application/pdf' && mimeType !== '.pdf') result = false; + }) + return result; + } + if (_typeErrorFiles.length > 0) { - if (mimeTypes.length === 1 && mimeTypes[0] === 'application/pdf') { + if (hasOnlyPdfMimeTypes(mimeTypes)) { _errorMessage.push(<>The specified file(s) {_typeErrorFiles.join(", ")} could not be uploaded. Only PDF filetypes are allowed.); } else { _errorMessage.push(<>The specified file(s) {_typeErrorFiles.join(", ")} could not be uploaded. Only files with the following extensions are allowed: {multipleFiles ? 'Excel (xls, xlsx, macro), pdf, image, word, email' : singleFileUploadAllowedFileExtensions}); From bf01db2d07fef40487a5aba11683007465bfe143 Mon Sep 17 00:00:00 2001 From: "sumathi.thirumani" Date: Mon, 15 Jan 2024 12:33:08 -0800 Subject: [PATCH 204/238] 4929 (Bug fix) Changes to validate user group (before open) --- request-management-api/request_api/models/FOIRawRequests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/request-management-api/request_api/models/FOIRawRequests.py b/request-management-api/request_api/models/FOIRawRequests.py index 7a244d0c8..8d5d4d0c9 100644 --- a/request-management-api/request_api/models/FOIRawRequests.py +++ b/request-management-api/request_api/models/FOIRawRequests.py @@ -629,7 +629,7 @@ def addadditionalfilter(cls, basequery, additionalfilter=None, userid=None, isia return basequery.filter( and_( FOIRawRequest.status.notin_(['Archived']), - or_(and_(FOIRawRequest.isiaorestricted == False, FOIRawRequest.assignedgroup.in_(ProcessingTeamWithKeycloackGroup.list())), and_(FOIRawRequest.isiaorestricted == True, FOIRawRequest.assignedto == userid)))) + or_(and_(FOIRawRequest.isiaorestricted == False, FOIRawRequest.assignedgroup.in_(ProcessingTeamWithKeycloackGroup.list()), FOIRawRequest.assignedgroup.in_(tuple(groups))), and_(FOIRawRequest.isiaorestricted == True, FOIRawRequest.assignedto == userid)))) return basequery.filter( and_( FOIRawRequest.status.notin_(['Archived']), From 1b756733b53c3326adcd1ff14f3eb030dcb8d613 Mon Sep 17 00:00:00 2001 From: Richard Qi Date: Mon, 15 Jan 2024 14:52:49 -0800 Subject: [PATCH 205/238] 1. add category id to applicant table 2. bug fix: compare the null and empty value before save applicant --- .../ba218164248e_add_category_to_applicant.py | 28 +++++++++++ .../models/FOIRequestApplicants.py | 50 +++++++++++-------- .../request_api/services/applicantservice.py | 1 + 3 files changed, 57 insertions(+), 22 deletions(-) create mode 100644 request-management-api/migrations/versions/ba218164248e_add_category_to_applicant.py diff --git a/request-management-api/migrations/versions/ba218164248e_add_category_to_applicant.py b/request-management-api/migrations/versions/ba218164248e_add_category_to_applicant.py new file mode 100644 index 000000000..007bec8a4 --- /dev/null +++ b/request-management-api/migrations/versions/ba218164248e_add_category_to_applicant.py @@ -0,0 +1,28 @@ +"""add category to applicant + +Revision ID: ba218164248e +Revises: 59a97f42b5f2 +Create Date: 2024-01-15 13:09:57.278888 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'ba218164248e' +down_revision = '59a97f42b5f2' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('FOIRequestApplicants', sa.Column('applicantcategoryid', sa.Integer(), nullable=True)) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('FOIRequestApplicants', 'applicantcategoryid') + # ### end Alembic commands ### \ No newline at end of file diff --git a/request-management-api/request_api/models/FOIRequestApplicants.py b/request-management-api/request_api/models/FOIRequestApplicants.py index 3c30b0269..1ac675099 100644 --- a/request-management-api/request_api/models/FOIRequestApplicants.py +++ b/request-management-api/request_api/models/FOIRequestApplicants.py @@ -18,7 +18,7 @@ class FOIRequestApplicant(db.Model): __tablename__ = 'FOIRequestApplicants' # Defining the columns foirequestapplicantid = db.Column(db.Integer, primary_key=True,autoincrement=True) - + firstname = db.Column(db.String(50), unique=False, nullable=True) middlename = db.Column(db.String(50), unique=False, nullable=True) lastname = db.Column(db.String(50), unique=False, nullable=True) @@ -26,7 +26,8 @@ class FOIRequestApplicant(db.Model): alsoknownas = db.Column(db.String(50), unique=False, nullable=True) dob = db.Column(db.DateTime, unique=False, nullable=True) businessname = db.Column(db.String(255), unique=False, nullable=True) - + applicantcategoryid = db.Column(db.Integer, unique=False, nullable=True) + created_at = db.Column(db.DateTime, default=datetime.now) updated_at = db.Column(db.DateTime, nullable=True) createdby = db.Column(db.String(120), unique=False, nullable=True) @@ -51,7 +52,7 @@ def createapplicant(cls, firstname, lastname, middlename, businessname, alsoknow return DefaultMethodResult(True,'Applicant added',applicant.foirequestapplicantid) @classmethod - def updateapplicantprofile(cls, foirequestapplicantid, firstname, lastname, middlename, businessname, alsoknownas, dob, userid): + def updateapplicantprofile(cls, foirequestapplicantid, firstname, lastname, middlename, businessname, alsoknownas, dob, applicantcategoryid, userid): applicant_query = db.session.query( FOIRequestApplicant ).filter_by( @@ -64,28 +65,21 @@ def updateapplicantprofile(cls, foirequestapplicantid, firstname, lastname, midd # applicant.isactive = False applicant_query.update({FOIRequestApplicant.applicantprofileid:str(uuid.uuid4())}) - if( - applicant.firstname != firstname - or applicant.lastname != lastname - or applicant.middlename != middlename - or applicant.businessname != businessname - or applicant.alsoknownas != alsoknownas - or applicant.dob != dob - ): + applicantfromform = FOIRequestApplicant().prepareapplicantforcomparing(firstname, lastname, middlename, businessname, alsoknownas, dob, applicantcategoryid) + applicantfromdb = FOIRequestApplicant().prepareapplicantforcomparing(applicant.firstname, applicant.lastname, applicant.middlename, applicant.businessname, applicant.alsoknownas, applicant.dob, applicant.applicantcategoryid) + if applicantfromform != applicantfromdb: _applicant = FOIRequestApplicant() _applicant.createdby = userid - _applicant.firstname = firstname - _applicant.lastname = lastname - _applicant.middlename = middlename - _applicant.businessname = businessname - _applicant.alsoknownas = alsoknownas + _applicant.firstname = applicantfromform.firstname + _applicant.lastname = applicantfromform.lastname + _applicant.middlename = applicantfromform.middlename + _applicant.businessname = applicantfromform.businessname + _applicant.alsoknownas = applicantfromform.alsoknownas + _applicant.dob = applicantfromform.dob _applicant.applicantprofileid = applicant.applicantprofileid - if dob is not None and dob != "": - _applicant.dob = dob - else: - _applicant.dob = None + _applicant.applicantcategoryid = applicantfromform.applicantcategoryid db.session.add(_applicant) - db.session.commit() + db.session.commit() return DefaultMethodResult(True,'Applicant profile updated',_applicant.foirequestapplicantid) else: return DefaultMethodResult(True,'No update',applicant.foirequestapplicantid) @@ -107,7 +101,7 @@ def getapplicantbyid(cls, applicantid): contactworkphone2 = aliased(FOIRequestContactInformation) contactmobilephone = aliased(FOIRequestContactInformation) contactother = aliased(FOIRequestContactInformation) - + city = aliased(FOIRequestContactInformation) province = aliased(FOIRequestContactInformation) postal = aliased(FOIRequestContactInformation) @@ -1175,6 +1169,18 @@ def getapplicantrequests(cls, applicantid): applicantrequest_schema = ApplicantRequestSchema(many=True) return applicantrequest_schema.dump(query_all.all()) + @classmethod + def prepareapplicantforcomparing(cls, firstname, lastname, middlename, businessname, alsoknownas, dob, applicantcategoryid): + return { + 'firstname': firstname if firstname is not None or firstname != '' else None, + 'lastname': lastname if lastname is not None or lastname != '' else None, + 'middlename': middlename if middlename is not None or middlename != '' else None, + 'businessname': businessname if businessname is not None or businessname != '' else None, + 'alsoknownas': alsoknownas if alsoknownas is not None or alsoknownas != '' else None, + 'dob': dob if dob is not None or dob != '' else None, + 'applicantcategoryid': applicantcategoryid if applicantcategoryid is not None or alsoknownas != 0 else None, + } + class FOIRequestApplicantSchema(ma.Schema): class Meta: diff --git a/request-management-api/request_api/services/applicantservice.py b/request-management-api/request_api/services/applicantservice.py index 84255796c..867509294 100644 --- a/request-management-api/request_api/services/applicantservice.py +++ b/request-management-api/request_api/services/applicantservice.py @@ -49,6 +49,7 @@ def saveapplicantinfo(self, applicantschema, userid): applicantschema['businessName'], applicantschema.get('additionalPersonalInfo', None).get('alsoKnownAs', None), applicantschema.get('additionalPersonalInfo', None).get('birthDate', None), + applicantschema['applicantCategoryID'], userid ) # replace with applicant id once new save function is written requests = FOIMinistryRequest.getopenrequestsbyrequestId(applicantschema['foirequestID']) From e070abbb6a510c1d82382dc9fe5c56b6e6118287 Mon Sep 17 00:00:00 2001 From: sumathi-thirumani-aot <57740789+sumathi-thirumani-aot@users.noreply.github.com> Date: Tue, 16 Jan 2024 09:44:16 -0800 Subject: [PATCH 206/238] Revert "4929 (Bug fix) Changes to validate user group (before open)" --- request-management-api/request_api/models/FOIRawRequests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/request-management-api/request_api/models/FOIRawRequests.py b/request-management-api/request_api/models/FOIRawRequests.py index 8d5d4d0c9..7a244d0c8 100644 --- a/request-management-api/request_api/models/FOIRawRequests.py +++ b/request-management-api/request_api/models/FOIRawRequests.py @@ -629,7 +629,7 @@ def addadditionalfilter(cls, basequery, additionalfilter=None, userid=None, isia return basequery.filter( and_( FOIRawRequest.status.notin_(['Archived']), - or_(and_(FOIRawRequest.isiaorestricted == False, FOIRawRequest.assignedgroup.in_(ProcessingTeamWithKeycloackGroup.list()), FOIRawRequest.assignedgroup.in_(tuple(groups))), and_(FOIRawRequest.isiaorestricted == True, FOIRawRequest.assignedto == userid)))) + or_(and_(FOIRawRequest.isiaorestricted == False, FOIRawRequest.assignedgroup.in_(ProcessingTeamWithKeycloackGroup.list())), and_(FOIRawRequest.isiaorestricted == True, FOIRawRequest.assignedto == userid)))) return basequery.filter( and_( FOIRawRequest.status.notin_(['Archived']), From 0c52cc0e03f833bc826f0eb2c69dddb19ac1a9a6 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 16 Jan 2024 12:04:07 -0800 Subject: [PATCH 207/238] minor ux improvements for loading and saving applicant info in modal after moving to open state --- .../FOI/foiApplicantProfileService.js | 4 ++- .../FOI/FOIRequest/ApplicantProfileModal.js | 24 ++++++++++-------- .../components/FOI/FOIRequest/FOIRequest.js | 25 +++++++++++-------- .../request_api/services/applicantservice.py | 1 + 4 files changed, 32 insertions(+), 22 deletions(-) diff --git a/forms-flow-web/src/apiManager/services/FOI/foiApplicantProfileService.js b/forms-flow-web/src/apiManager/services/FOI/foiApplicantProfileService.js index 9801e1024..5ca7c4647 100644 --- a/forms-flow-web/src/apiManager/services/FOI/foiApplicantProfileService.js +++ b/forms-flow-web/src/apiManager/services/FOI/foiApplicantProfileService.js @@ -5,7 +5,8 @@ import { import API from "../../endpoints"; import { serviceActionError, - setRestrictedReqTaglist + setRestrictedReqTaglist, + setFOILoader } from "../../../actions/FOI/foiRequestActions"; import { catchError, fnDone} from './foiServicesUtil'; import UserService from "../../../services/UserService"; @@ -145,6 +146,7 @@ export const saveApplicantInfo = (applicant, ...rest) => { .then((res) => { if (res.data) { dispatch(setRestrictedReqTaglist(res.data)); + dispatch(setFOILoader(false)); done(null, res.data); } else { dispatch(serviceActionError(res)); diff --git a/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js b/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js index 7f058ff5f..313fa018a 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js @@ -33,8 +33,9 @@ import AccordionDetails from '@material-ui/core/AccordionDetails'; import Typography from '@material-ui/core/Typography'; import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import { StateEnum } from "../../../constants/FOI/statusEnum"; -import { setFOIRequestApplicantProfile } from "../../../actions/FOI/foiRequestActions"; +import { setFOIRequestApplicantProfile, setFOILoader } from "../../../actions/FOI/foiRequestActions"; import { toast } from "react-toastify"; +import Loading from "../../../containers/Loading"; const useStyles = makeStyles((theme) => ({ root: { @@ -138,9 +139,11 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { setRows(res); setIsLoading(false); })) - } else { + } else { + setSelectedApplicant(true); dispatch(fetchApplicantInfo(requestDetails.foiRequestApplicantID, (err, res) => { setSelectedApplicant(res); + setIsLoading(false); })) } } @@ -149,9 +152,9 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { useEffect(() => { setSaveApplicantObject({...selectedApplicant}) for (let field in selectedApplicant) { - if (field === 'additionalPersonalInfo' && requestDetails[field] && requestDetails.requestType === 'personal') { - if ((requestDetails[field][FOI_COMPONENT_CONSTANTS.DOB] && selectedApplicant[field][FOI_COMPONENT_CONSTANTS.DOB] !== requestDetails[field][FOI_COMPONENT_CONSTANTS.DOB]) || - (requestDetails[field][FOI_COMPONENT_CONSTANTS.PERSONAL_HEALTH_NUMBER] && selectedApplicant[field][FOI_COMPONENT_CONSTANTS.PERSONAL_HEALTH_NUMBER] !== requestDetails[field][FOI_COMPONENT_CONSTANTS.PERSONAL_HEALTH_NUMBER])) { + if (field === 'additionalPersonalInfo') { + if (requestDetails[field] && requestDetails.requestType === 'personal' && ((requestDetails[field][FOI_COMPONENT_CONSTANTS.DOB] && selectedApplicant[field][FOI_COMPONENT_CONSTANTS.DOB] !== requestDetails[field][FOI_COMPONENT_CONSTANTS.DOB]) || + (requestDetails[field][FOI_COMPONENT_CONSTANTS.PERSONAL_HEALTH_NUMBER] && selectedApplicant[field][FOI_COMPONENT_CONSTANTS.PERSONAL_HEALTH_NUMBER] !== requestDetails[field][FOI_COMPONENT_CONSTANTS.PERSONAL_HEALTH_NUMBER]))) { setIsProfileDifferent(true); break; } @@ -265,15 +268,14 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { } const selectProfile = () => { - if (_.isEqual(selectedApplicant, saveApplicantObject) || confirmationMessage) { - if (requestDetails.currentState === StateEnum.intakeinprogress.name) { - dispatch(setFOIRequestApplicantProfile(saveApplicantObject)); - } + if (_.isEqual(selectedApplicant, saveApplicantObject) || confirmationMessage) { + handleClose(); // set loading screen + dispatch(setFOILoader(true)); dispatch(saveApplicantInfo(saveApplicantObject, (err, res) => { if (!err) { // unset loading screen - handleClose(); + dispatch(setFOIRequestApplicantProfile(saveApplicantObject)); } })); } else { @@ -435,7 +437,7 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { })} : - <> + isLoading ? : <> {isProfileDifferent && Some of the fields in this profile do not match your original request. diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index c6ad8617d..767c70189 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -339,19 +339,24 @@ const FOIRequest = React.memo(({ userDetail, openApplicantProfileModal }) => { }, [requestDetails]); useEffect(() => { - if (requestApplicantProfile) { - let newRequestDetails = { ...saveRequestObject }; - for (let field in requestApplicantProfile) { - if (field === "additionalPersonalInfo") { - for (let infofield in requestApplicantProfile[field]) { - newRequestDetails[field][infofield] = - requestApplicantProfile[field][infofield]; + if (requestApplicantProfile) { + if (requestDetails.currentState === StateEnum.intakeinprogress.name) { + let newRequestDetails = { ...saveRequestObject }; + for (let field in requestApplicantProfile) { + if (field === "additionalPersonalInfo") { + newRequestDetails["additionalPersonalInfo"] = newRequestDetails["additionalPersonalInfo"] || {} + for (let infofield in requestApplicantProfile[field]) { + newRequestDetails[field][infofield] = + requestApplicantProfile[field][infofield]; + } + } else { + newRequestDetails[field] = requestApplicantProfile[field]; } - } else { - newRequestDetails[field] = requestApplicantProfile[field]; } + dispatch(setFOIRequestDetail(newRequestDetails)) + } else { + handleSaveRequest(requestDetails.currentState, false, ""); } - dispatch(setFOIRequestDetail(newRequestDetails)) } }, [requestApplicantProfile]); diff --git a/request-management-api/request_api/services/applicantservice.py b/request-management-api/request_api/services/applicantservice.py index 54f69c0ba..d72ccd7c9 100644 --- a/request-management-api/request_api/services/applicantservice.py +++ b/request-management-api/request_api/services/applicantservice.py @@ -30,6 +30,7 @@ def getapplicantbyid(self, applicantid): applicant = FOIRequestApplicant.getapplicantbyid(applicantid) applicant = self.__prepareapplicant(applicant) applicant['requestHistory'] = self.getapplicantrequests(applicantid) + applicant.pop('requestType') return applicant def searchapplicant(self, keywords): From eb87fd7274fe7750cd6bc68ea812e298ca04e920 Mon Sep 17 00:00:00 2001 From: divyav-aot Date: Tue, 16 Jan 2024 16:13:44 -0500 Subject: [PATCH 208/238] fix for dismiss notification raw request --- .../request_api/models/FOIRawRequestNotificationUsers.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/request-management-api/request_api/models/FOIRawRequestNotificationUsers.py b/request-management-api/request_api/models/FOIRawRequestNotificationUsers.py index 2f114310d..3533c4aab 100644 --- a/request-management-api/request_api/models/FOIRawRequestNotificationUsers.py +++ b/request-management-api/request_api/models/FOIRawRequestNotificationUsers.py @@ -96,10 +96,10 @@ def getnotificationsbyuser(cls, userid): return notifications @classmethod - def getnotificationsbyuserandtype(cls, userid, typeid): - for key in notificationusertypes_cache: - if (notificationusertypes_cache[key].notificationusertypeid == typeid) or (notificationusertypes_cache[key].notificationusertypelabel == typeid): - notificationusertypelabel = notificationusertypes_cache[key].notificationusertypelabel + def getnotificationsbyuserandtype(cls, userid, notificationusertypelabel): + # for key in notificationusertypes_cache: + # if (notificationusertypes_cache[key].notificationusertypeid == typeid) or (notificationusertypes_cache[key].notificationusertypelabel == typeid): + # notificationusertypelabel = notificationusertypes_cache[key].notificationusertypelabel notifications = [] try: sql = """select notificationid, count(1) as relcount from "FOIRawRequestNotificationUsers" frnu From a847723ced990a7c7d197cd141e90f84e01e799c Mon Sep 17 00:00:00 2001 From: divyav-aot Date: Tue, 16 Jan 2024 18:07:48 -0500 Subject: [PATCH 209/238] dismiss notification related to tagged comments and triggered user is fixed --- .../common/notificationusertypes.json | 2 +- .../dao/models/NotificationUserTypes.py | 20 +++++++++++ .../notifications/notificationconfig.py | 33 ++++++++++++++----- .../notifications/notificationuser.py | 10 +++--- .../services/notificationservice.py | 8 ++--- .../common/notificationusertypes.json | 4 +-- 6 files changed, 57 insertions(+), 20 deletions(-) diff --git a/notification-manager/common/notificationusertypes.json b/notification-manager/common/notificationusertypes.json index 0ea835c44..0964c4f59 100644 --- a/notification-manager/common/notificationusertypes.json +++ b/notification-manager/common/notificationusertypes.json @@ -25,6 +25,6 @@ "name": "Triggered User", "description": "Triggered User", "isactive": true, - "notificationusertypelabel": "triggereduser" + "notificationusertypelabel": "assignee" } } diff --git a/notification-manager/notification_api/dao/models/NotificationUserTypes.py b/notification-manager/notification_api/dao/models/NotificationUserTypes.py index ae06e67f6..99bd7be46 100644 --- a/notification-manager/notification_api/dao/models/NotificationUserTypes.py +++ b/notification-manager/notification_api/dao/models/NotificationUserTypes.py @@ -26,3 +26,23 @@ def getid(self, name): finally: if conn: conn.close() + + def getidbylabel(self, label): + conn = None + try: + _notificationusertypes = [] + conn = getconnection() + cursor = conn.cursor() + cursor.execute("""select notificationusertypeid from "NotificationUserTypes" nt where isactive = true and notificationusertypelabel = '{0}'""".format(label)) + data = cursor.fetchone() + if data is not None: + data = {"notificationusertypeid": data[0]} + return data + + cursor.close() + return _notificationusertypes + except(Exception) as error: + logging.error(error) + finally: + if conn: + conn.close() diff --git a/notification-manager/notification_api/services/notifications/notificationconfig.py b/notification-manager/notification_api/services/notifications/notificationconfig.py index 6b18da016..215a969b0 100644 --- a/notification-manager/notification_api/services/notifications/notificationconfig.py +++ b/notification-manager/notification_api/services/notifications/notificationconfig.py @@ -5,32 +5,47 @@ import os from notification_api.dao.models.NotificationTypes import NotificationType from notification_api.dao.models.NotificationUserTypes import NotificationUserType +notificationuserfile = open('common/notificationusertypes.json', encoding="utf8") +notificationusertypes_cache = json.load(notificationuserfile) + +notificationfile = open('common/notificationtypes.json', encoding="utf8") +notificationtypes_cache = json.load(notificationfile) class notificationconfig: """ Notfication config """ - - def getnotificationtypeid(self, notificationtype): - notificationid = NotificationType().getid(notificationtype) - if notificationid is not None: - return notificationid - def getnotificationtype(self, notificationtype): notificationid = NotificationType().getid(notificationtype) if notificationid is not None: return notificationid - def getnotificationusertypeid(self, notificationusertype): + def getnotificationusertype(self, notificationusertype): notificationuserid = NotificationUserType().getid(notificationusertype) if notificationuserid is not None: return notificationuserid + - def getnotificationusertype(self, notificationusertype): - notificationuserid = NotificationUserType().getid(notificationusertype) + # This method is used to get the notification user type label + # It first tries to get the notification user type label from the cache + # If it is not found in the cache, it fetches it from the DB + def getnotificationusertypelabel(self, notificationusertype): + notificationusertype_format = notificationusertype.replace(" ", "").lower() + if notificationusertype_format in notificationusertypes_cache: + return notificationusertypes_cache[notificationusertype_format]['notificationusertypelabel'] + else: + print("Notification user type not found in json. Fetching from DB", notificationusertype) + notificationusertypeobj = self.getnotificationusertype(notificationusertype) + if notificationusertypeobj is not None: + return notificationusertypeobj['notificationusertypelabel'] + return None + + def getnotificationusertypeidbylabel(self, label): + notificationuserid = NotificationUserType().getidbylabel(label) if notificationuserid is not None: return notificationuserid + def getnotificationdays(self): if 'FOI_NOTIFICATION_DAYS' in os.environ and os.getenv('FOI_NOTIFICATION_DAYS') != '': return os.getenv('FOI_NOTIFICATION_DAYS') diff --git a/notification-manager/notification_api/services/notifications/notificationuser.py b/notification-manager/notification_api/services/notifications/notificationuser.py index 35341738f..24e99537c 100644 --- a/notification-manager/notification_api/services/notifications/notificationuser.py +++ b/notification-manager/notification_api/services/notifications/notificationuser.py @@ -53,22 +53,24 @@ def __istaggeduser(self, notificationuser, foicomment, notificationtype): def __gettriggereduser(self, userid, notificationtype): notificationusers = [] + notificationtypelabel = "assignee" if notificationtype in ["Records", "PDFStitch"]: - notificationusers.append({"userid":userid, "usertype":notificationconfig().getnotificationusertype("Triggered User")['notificationusertypelabel']}) + notificationusers.append({"userid":userid, "usertype":notificationtypelabel}) return notificationusers def __getwatchers(self, notificationtype, foirequest, requesttype, requestjson=None): notificationusers = [] - if notificationtype == "Watcher": - notificationusers.append({"userid": requestjson['watchedby'], "usertype":notificationconfig().getnotificationusertype("Watcher")['notificationusertypelabel']}) + notificationtypelabel = "watcher" + if notificationtype == "Watcher": + notificationusers.append({"userid": requestjson['watchedby'], "usertype":notificationtypelabel}) else: if requesttype == "ministryrequest": watchers = FOIMinistryRequest().getwatchers(foirequest["foiministryrequestid"]) else: watchers = FOIRawRequest().getwatchers(foirequest['requestid']) for watcher in watchers: - notificationusers.append({"userid":watcher["watchedby"], "usertype":notificationconfig().getnotificationusertype("Watcher")['notificationusertypelabel']}) + notificationusers.append({"userid":watcher["watchedby"], "usertype":notificationtypelabel}) return notificationusers def __getassignees(self, foirequest, requesttype, notificationtype, requestjson=None): diff --git a/notification-manager/notification_api/services/notificationservice.py b/notification-manager/notification_api/services/notificationservice.py index 3a9df645d..aa6fe43fe 100644 --- a/notification-manager/notification_api/services/notificationservice.py +++ b/notification-manager/notification_api/services/notificationservice.py @@ -87,10 +87,10 @@ def __preparenotificationuser(self, notificationid, notificationuser, userid, mu usertype = notificationusertypes_cache[notificationuser["usertype"]] if usertype is None: print('User type not found', notificationuser["usertype"]) - return None - notificationtypes = notificationconfig().getnotificationusertype(usertype['name']) - user.notificationusertypelabel = notificationtypes['notificationusertypelabel'] - user.notificationusertypeid = notificationtypes['notificationusertypeid'] + return None + notificationusertypelabel = notificationconfig().getnotificationusertypelabel(usertype['name']) + user.notificationusertypelabel = notificationusertypelabel + user.notificationusertypeid = notificationconfig().getnotificationusertypeidbylabel(notificationusertypelabel)['notificationusertypeid'] user.notificationid = notificationid user.userid = notificationuser["userid"] user.createdby = userid diff --git a/request-management-api/common/notificationusertypes.json b/request-management-api/common/notificationusertypes.json index 1048cc990..8efa082d3 100644 --- a/request-management-api/common/notificationusertypes.json +++ b/request-management-api/common/notificationusertypes.json @@ -46,13 +46,13 @@ "name": "comment tagged user", "description": "Comment User", "isactive": true, - "notificationusertypelabel": "commentuser" + "notificationusertypelabel": "assignee" }, "triggereduser": { "notificationusertypeid": 4, "name": "Triggered User", "description": "Triggered User", "isactive": true, - "notificationusertypelabel": "triggereduser" + "notificationusertypelabel": "assignee" } } From 4082abbe7576dae1004af2add9e9c7b1a250fe25 Mon Sep 17 00:00:00 2001 From: divyav-aot Date: Tue, 16 Jan 2024 18:09:38 -0500 Subject: [PATCH 210/238] removed commented lines --- .../request_api/models/FOIRawRequestNotificationUsers.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/request-management-api/request_api/models/FOIRawRequestNotificationUsers.py b/request-management-api/request_api/models/FOIRawRequestNotificationUsers.py index 3533c4aab..9d3b15523 100644 --- a/request-management-api/request_api/models/FOIRawRequestNotificationUsers.py +++ b/request-management-api/request_api/models/FOIRawRequestNotificationUsers.py @@ -97,9 +97,6 @@ def getnotificationsbyuser(cls, userid): @classmethod def getnotificationsbyuserandtype(cls, userid, notificationusertypelabel): - # for key in notificationusertypes_cache: - # if (notificationusertypes_cache[key].notificationusertypeid == typeid) or (notificationusertypes_cache[key].notificationusertypelabel == typeid): - # notificationusertypelabel = notificationusertypes_cache[key].notificationusertypelabel notifications = [] try: sql = """select notificationid, count(1) as relcount from "FOIRawRequestNotificationUsers" frnu From 91b62986c623361c61dcda2275cf55fd7961dd7c Mon Sep 17 00:00:00 2001 From: Richard Qi Date: Tue, 16 Jan 2024 16:22:04 -0800 Subject: [PATCH 211/238] 1. update search to search all history 2. bug fix: compare dob 3. return applicant category --- .../models/FOIRequestApplicants.py | 60 +++++++++++++++---- .../request_api/services/applicantservice.py | 3 +- 2 files changed, 49 insertions(+), 14 deletions(-) diff --git a/request-management-api/request_api/models/FOIRequestApplicants.py b/request-management-api/request_api/models/FOIRequestApplicants.py index 1ac675099..109d4fadf 100644 --- a/request-management-api/request_api/models/FOIRequestApplicants.py +++ b/request-management-api/request_api/models/FOIRequestApplicants.py @@ -371,6 +371,9 @@ def getapplicantbyemail(cls, email): personalcorrectionnumber = aliased(FOIRequestPersonalAttribute) personalhealthnumber = aliased(FOIRequestPersonalAttribute) + #aliase for search + searchcontactemail = aliased(FOIRequestContactInformation) + #max foirequest version subquery_foirequest_maxversion = _session.query(FOIRequest.foirequestid, func.max(FOIRequest.version).label('max_version')).group_by(FOIRequest.foirequestid).subquery() joincondition = [ @@ -412,6 +415,8 @@ def getapplicantbyemail(cls, email): subquery_all = _session.query( *selectedcolumns + ).distinct( + FOIRequest.foirequestid ).join( FOIRequestApplicantMapping, and_( @@ -560,12 +565,18 @@ def getapplicantbyemail(cls, email): personalhealthnumber.personalattributeid == 3, personalhealthnumber.attributevalue is not None), isouter=True + ).join( + searchcontactemail, + and_( + searchcontactemail.foirequest_id == FOIRequest.foirequestid, + searchcontactemail.contacttypeid == 1, + searchcontactemail.contactinformation == email), ).filter( # FOIMinistryRequest.requeststatusid != 3, - FOIRequest.isactive == True, - contactemail.contactinformation == email + FOIRequest.isactive == True + # searchcontactemail.contactinformation == email ).order_by(FOIRequest.foirequestid.desc()).subquery() - + query_aggregate = _session.query( func.array_agg(subquery_all.c.applicantprofileid).label('applicantprofileid'), func.array_agg(subquery_all.c.updatedat).label('updatedat'), @@ -627,6 +638,11 @@ def searchapplicant(cls, keywords): personalcorrectionnumber = aliased(FOIRequestPersonalAttribute) personalhealthnumber = aliased(FOIRequestPersonalAttribute) + #aliase for search + searchapplicant = aliased(FOIRequestApplicant) + searchapplicantmapping = aliased(FOIRequestApplicantMapping) + searchcontactinfo = aliased(FOIRequestContactInformation) + #max foirequest version subquery_foirequest_maxversion = _session.query(FOIRequest.foirequestid, func.max(FOIRequest.version).label('max_version')).group_by(FOIRequest.foirequestid).subquery() joincondition = [ @@ -667,6 +683,8 @@ def searchapplicant(cls, keywords): subquery_all = _session.query( *selectedcolumns + ).distinct( + FOIRequest.foirequestid ).join( FOIRequestApplicantMapping, and_( @@ -806,10 +824,26 @@ def searchapplicant(cls, keywords): personalhealthnumber.personalattributeid == 3, personalhealthnumber.attributevalue is not None), isouter=True + ).join( + searchapplicantmapping, + and_( + searchapplicantmapping.foirequest_id == FOIRequest.foirequestid, + searchapplicantmapping.requestortypeid == 1), + isouter=True + ).join( + searchapplicant, + searchapplicant.foirequestapplicantid == searchapplicantmapping.foirequestapplicantid, + isouter=True + ).join( + searchcontactinfo, + and_( + searchcontactinfo.foirequest_id == FOIRequest.foirequestid, + contacthomephone.contactinformation is not None), + isouter=True ).filter( # FOIMinistryRequest.requeststatusid != 3, FOIRequest.isactive == True, - or_(*FOIRequestApplicant.getsearchfilters(keywords, contactemail, contacthomephone, contactworkphone, contactworkphone2, contactmobilephone)) + or_(*FOIRequestApplicant.getsearchfilters(searchapplicant, searchcontactinfo, keywords, contactemail, contacthomephone, contactworkphone, contactworkphone2, contactmobilephone)) ).order_by(FOIRequest.foirequestid.desc()).subquery() query_aggregate = _session.query( @@ -847,29 +881,29 @@ def searchapplicant(cls, keywords): @classmethod - def getsearchfilters(cls, keywords, contactemail, contacthomephone, contactworkphone, contactworkphone2, contactmobilephone): + def getsearchfilters(cls, searchapplicant, searchcontactinfo, keywords, contactemail, contacthomephone, contactworkphone, contactworkphone2, contactmobilephone): searchfilters = [] if(len(keywords) > 0): if('firstname' in keywords): - searchfilters.append(FOIRequestApplicant.firstname.ilike('%'+keywords['firstname']+'%')) + searchfilters.append(searchapplicant.firstname.ilike('%'+keywords['firstname']+'%')) if('lastname' in keywords): - searchfilters.append(FOIRequestApplicant.lastname.ilike('%'+keywords['lastname']+'%')) + searchfilters.append(searchapplicant.lastname.ilike('%'+keywords['lastname']+'%')) if('email' in keywords): - searchfilters.append(contactemail.contactinformation.ilike('%'+keywords['email']+'%')) + searchfilters.append(searchcontactinfo.contactinformation.ilike('%'+keywords['email']+'%')) if('homephone' in keywords): - searchfilters.append(contacthomephone.contactinformation.ilike('%'+keywords['homephone']+'%')) + searchfilters.append(searchcontactinfo.contactinformation.ilike('%'+keywords['homephone']+'%')) if('workphone' in keywords): - searchfilters.append(contactworkphone.contactinformation.ilike('%'+keywords['workphone']+'%')) + searchfilters.append(searchcontactinfo.contactinformation.ilike('%'+keywords['workphone']+'%')) if('workphone2' in keywords): - searchfilters.append(contactworkphone2.contactinformation.ilike('%'+keywords['workphone2']+'%')) + searchfilters.append(searchcontactinfo.contactinformation.ilike('%'+keywords['workphone2']+'%')) if('mobilephone' in keywords): - searchfilters.append(contactmobilephone.contactinformation.ilike('%'+keywords['mobilephone']+'%')) + searchfilters.append(searchcontactinfo.contactinformation.ilike('%'+keywords['mobilephone']+'%')) return searchfilters @@ -1177,7 +1211,7 @@ def prepareapplicantforcomparing(cls, firstname, lastname, middlename, businessn 'middlename': middlename if middlename is not None or middlename != '' else None, 'businessname': businessname if businessname is not None or businessname != '' else None, 'alsoknownas': alsoknownas if alsoknownas is not None or alsoknownas != '' else None, - 'dob': dob if dob is not None or dob != '' else None, + 'dob': datetime.strptime(dob, "%Y-%m-%d") if dob is not None or dob != '' else None, 'applicantcategoryid': applicantcategoryid if applicantcategoryid is not None or alsoknownas != 0 else None, } diff --git a/request-management-api/request_api/services/applicantservice.py b/request-management-api/request_api/services/applicantservice.py index 867509294..a85c72087 100644 --- a/request-management-api/request_api/services/applicantservice.py +++ b/request-management-api/request_api/services/applicantservice.py @@ -94,7 +94,7 @@ def __prepareapplicant(self, applicant): 'foirequestID': applicant["foirequestid"], 'foirequestVersion': applicant["foirequestversion"], 'requestType': applicant["requesttype"], - # 'category': applicant["applicantcategory"], + 'category': applicant["applicantcategory"], 'email': self.__first_not_null(applicant["email"]), 'address': self.__first_not_null(applicant["address"]), 'city': self.__first_not_null(applicant["city"]), @@ -151,6 +151,7 @@ def __prepareapplicantforcomparing(self, applicant): 'Other Contact Info': applicant["othercontactinfo"], 'Employee Number': applicant["employeenumber"], 'Corrections Number': applicant["correctionnumber"], + 'Applicant Category': applicant["applicantcategory"], } def getapplicantrequests(self, applicantid): From 535aaac77eed67d24918abada794e83f6dfcf3f3 Mon Sep 17 00:00:00 2001 From: divyav-aot Date: Tue, 16 Jan 2024 19:50:02 -0500 Subject: [PATCH 212/238] CFR notification for watcher: fixed --- request-management-api/request_api/services/events/state.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/request-management-api/request_api/services/events/state.py b/request-management-api/request_api/services/events/state.py index 877009889..d5b015d43 100644 --- a/request-management-api/request_api/services/events/state.py +++ b/request-management-api/request_api/services/events/state.py @@ -63,7 +63,6 @@ def __createnotification(self, requestid, state, requesttype, userid): if state == StateName.callforrecords.value and requesttype == "ministryrequest": foirequest = notificationservice().getrequest(requestid, requesttype) _notificationtype = "Group Members" if foirequest['assignedministryperson'] is None else "State" - notificationtype = NotificationType().getnotificationtypeid(_notificationtype) notification = self.__preparenotification(state) if state == StateName.response.value and requesttype == "ministryrequest": signgoffapproval = FOIMinistryRequest().getrequest(requestid)['ministrysignoffapproval'] @@ -74,10 +73,13 @@ def __createnotification(self, requestid, state, requesttype, userid): if state == StateName.archived.value: _openedministries = FOIMinistryRequest.getministriesopenedbyuid(requestid) for ministry in _openedministries: + notificationtype = NotificationType().getnotificationtypeid("State") response = notificationservice().createnotification({"message" : notification}, ministry["ministryrequestid"], 'ministryrequest', notificationtype, userid) else: + notificationtype = NotificationType().getnotificationtypeid("State") response = notificationservice().createnotification({"message" : notification}, requestid, requesttype, notificationtype, userid) if _notificationtype == "Group Members": + notificationtype = NotificationType().getnotificationtypeid(_notificationtype) notification = self.__preparegroupmembernotification(state, requestid) groupmemberresponse = notificationservice().createnotification({"message" : notification}, requestid, requesttype, notificationtype, userid) if response.success == True and groupmemberresponse.success == True : From 91b8d3dca9df9880cb4b31bc4bc099c2eba49e04 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 17 Jan 2024 15:46:10 -0800 Subject: [PATCH 213/238] fix different dob data type causing update bug add aka field to profile modal --- .../FOI/FOIRequest/ApplicantDetails.js | 22 +++++++++++++++++++ .../FOI/FOIRequest/ApplicantProfileModal.js | 19 ++++++++++------ .../constants/FOI/foiComponentConstants.js | 1 + .../models/FOIRequestApplicants.py | 2 +- 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/ApplicantDetails.js b/forms-flow-web/src/components/FOI/FOIRequest/ApplicantDetails.js index 728018def..9c01c5efb 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/ApplicantDetails.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/ApplicantDetails.js @@ -106,6 +106,9 @@ const ApplicantDetails = React.memo( defaultValue: "Select Category", }) ); + const [alsoKnownAsText, setAlsoKnownAs] = React.useState( + validateFields(requestDetails?.additionalPersonalInfo, FOI_COMPONENT_CONSTANTS.ALSO_KNOWN_AS) + ); //handle initial value for required field validation React.useEffect(() => { @@ -213,6 +216,14 @@ const ApplicantDetails = React.memo( ); }; + const handleAlsoKnownAsChange = (e) => { + setAlsoKnownAs(e.target.value); + createSaveRequestObject( + FOI_COMPONENT_CONSTANTS.ALSO_KNOWN_AS, + e.target.value + ); + }; + //generate the menu items for the category const menuItems = category.map((item) => { return ( @@ -307,6 +318,17 @@ const ApplicantDetails = React.memo( > {menuItems} + {showHistory && }
diff --git a/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js b/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js index 313fa018a..c101b074c 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js @@ -153,10 +153,13 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { setSaveApplicantObject({...selectedApplicant}) for (let field in selectedApplicant) { if (field === 'additionalPersonalInfo') { - if (requestDetails[field] && requestDetails.requestType === 'personal' && ((requestDetails[field][FOI_COMPONENT_CONSTANTS.DOB] && selectedApplicant[field][FOI_COMPONENT_CONSTANTS.DOB] !== requestDetails[field][FOI_COMPONENT_CONSTANTS.DOB]) || - (requestDetails[field][FOI_COMPONENT_CONSTANTS.PERSONAL_HEALTH_NUMBER] && selectedApplicant[field][FOI_COMPONENT_CONSTANTS.PERSONAL_HEALTH_NUMBER] !== requestDetails[field][FOI_COMPONENT_CONSTANTS.PERSONAL_HEALTH_NUMBER]))) { - setIsProfileDifferent(true); - break; + if (requestDetails[field] && requestDetails.requestType === 'personal') { + for (let additionalField in requestDetails[field]) { + if (requestDetails[field][additionalField] && selectedApplicant[field][additionalField] !== requestDetails[field][additionalField]) { + setIsProfileDifferent(true); + break; + } + } } } else if (requestDetails[field] && selectedApplicant[field] !== requestDetails[field]) { setIsProfileDifferent(true); @@ -167,8 +170,10 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { const createSaveApplicantObject = (name, value, value2) => { let newApplicantObj = {...saveApplicantObject} - if ([FOI_COMPONENT_CONSTANTS.DOB, FOI_COMPONENT_CONSTANTS.PERSONAL_HEALTH_NUMBER].includes(name)) { - newApplicantObj.additionalPersonalInfo[name] = value; + if ([FOI_COMPONENT_CONSTANTS.DOB, FOI_COMPONENT_CONSTANTS.PERSONAL_HEALTH_NUMBER, FOI_COMPONENT_CONSTANTS.ALSO_KNOWN_AS].includes(name)) { + let additionalPersonalInfo = {...newApplicantObj.additionalPersonalInfo} + additionalPersonalInfo[name] = value + newApplicantObj.additionalPersonalInfo = additionalPersonalInfo; } else { newApplicantObj[name] = value; } @@ -591,7 +596,7 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { <>{!applicantHistory && } diff --git a/forms-flow-web/src/constants/FOI/foiComponentConstants.js b/forms-flow-web/src/constants/FOI/foiComponentConstants.js index b8fbb45c8..2d0cd5918 100644 --- a/forms-flow-web/src/constants/FOI/foiComponentConstants.js +++ b/forms-flow-web/src/constants/FOI/foiComponentConstants.js @@ -49,6 +49,7 @@ const FOI_COMPONENT_CONSTANTS = { PERSONAL_HEALTH_NUMBER: "personalHealthNumber", CORRECTIONS_NUMBER: "correctionalServiceNumber", DOB: "birthDate", + ALSO_KNOWN_AS: "alsoKnownAs", EMPLOYEE_NUMBER: "publicServiceEmployeeNumber", IDENTITY_VERIFIED: "identityVerified", diff --git a/request-management-api/request_api/models/FOIRequestApplicants.py b/request-management-api/request_api/models/FOIRequestApplicants.py index 3c30b0269..6171d9127 100644 --- a/request-management-api/request_api/models/FOIRequestApplicants.py +++ b/request-management-api/request_api/models/FOIRequestApplicants.py @@ -70,7 +70,7 @@ def updateapplicantprofile(cls, foirequestapplicantid, firstname, lastname, midd or applicant.middlename != middlename or applicant.businessname != businessname or applicant.alsoknownas != alsoknownas - or applicant.dob != dob + or applicant.dob != datetime.strptime(dob, "%Y-%m-%d") ): _applicant = FOIRequestApplicant() _applicant.createdby = userid From 63889c43c921e333b5db79567a95a4c351f937c8 Mon Sep 17 00:00:00 2001 From: Richard Qi Date: Thu, 18 Jan 2024 11:45:36 -0800 Subject: [PATCH 214/238] save categoryid to applicant table --- .../request_api/models/FOIRequestApplicants.py | 5 +++-- .../services/foirequest/requestservicebuilder.py | 4 ++-- .../services/foirequest/requestservicecreate.py | 9 ++++++--- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/request-management-api/request_api/models/FOIRequestApplicants.py b/request-management-api/request_api/models/FOIRequestApplicants.py index 109d4fadf..12e388acc 100644 --- a/request-management-api/request_api/models/FOIRequestApplicants.py +++ b/request-management-api/request_api/models/FOIRequestApplicants.py @@ -35,7 +35,7 @@ class FOIRequestApplicant(db.Model): applicantprofileid = db.Column(db.String(120), unique=False, nullable=True) @classmethod - def createapplicant(cls, firstname, lastname, middlename, businessname, alsoknownas, dob, userid): + def createapplicant(cls, firstname, lastname, middlename, businessname, alsoknownas, dob, applicantcategoryid, userid): applicant = FOIRequestApplicant() applicant.createdby = userid applicant.firstname = firstname @@ -43,8 +43,9 @@ def createapplicant(cls, firstname, lastname, middlename, businessname, alsoknow applicant.middlename = middlename applicant.businessname = businessname applicant.alsoknownas = alsoknownas + applicant.applicantcategoryid = applicantcategoryid if dob is not None and dob != "": - applicant.dob = dob + applicant.dob = datetime.strptime(dob, "%Y-%m-%d") else: applicant.dob = None db.session.add(applicant) diff --git a/request-management-api/request_api/services/foirequest/requestservicebuilder.py b/request-management-api/request_api/services/foirequest/requestservicebuilder.py index 0f214e3ba..1a812b827 100644 --- a/request-management-api/request_api/services/foirequest/requestservicebuilder.py +++ b/request-management-api/request_api/services/foirequest/requestservicebuilder.py @@ -107,9 +107,9 @@ def createcontactinformation(self,dataformat, name, value, contacttypes, userid) contactinformation.contacttypeid =contacttype["contacttypeid"] return contactinformation - def createapplicant(self,firstname, lastname, appltcategory, userid, middlename = None,businessname = None, alsoknownas = None, dob = None): + def createapplicant(self,firstname, lastname, appltcategory, userid, middlename = None, businessname = None, alsoknownas = None, dob = None, applicantcategoryid = None): requestapplicant = FOIRequestApplicantMapping() - _applicant = FOIRequestApplicant().createapplicant(firstname, lastname, middlename, businessname, alsoknownas, dob, userid) + _applicant = FOIRequestApplicant().createapplicant(firstname, lastname, middlename, businessname, alsoknownas, dob, applicantcategoryid, userid) requestapplicant.foirequestapplicantid = _applicant.identifier if appltcategory is not None: requestertype = RequestorType().getrequestortype(appltcategory) diff --git a/request-management-api/request_api/services/foirequest/requestservicecreate.py b/request-management-api/request_api/services/foirequest/requestservicecreate.py index f1689010b..1a7cb8a2f 100644 --- a/request-management-api/request_api/services/foirequest/requestservicecreate.py +++ b/request-management-api/request_api/services/foirequest/requestservicecreate.py @@ -39,8 +39,8 @@ def saverequest(self,foirequestschema, userid, foirequestid=None, ministryid=Non openfoirequest.deliverymodeid = requestserviceconfigurator().getvalueof("deliveryMode",foirequestschema.get("deliveryMode")) if requestservicebuilder().isNotBlankorNone(foirequestschema,"receivedMode","main") == True: openfoirequest.receivedmodeid = requestserviceconfigurator().getvalueof("receivedMode",foirequestschema.get("receivedMode")) - if requestservicebuilder().isNotBlankorNone(foirequestschema,"category","main") == True: - openfoirequest.applicantcategoryid = requestserviceconfigurator().getvalueof("category",foirequestschema.get("category")) + # if requestservicebuilder().isNotBlankorNone(foirequestschema,"category","main") == True: + # openfoirequest.applicantcategoryid = requestserviceconfigurator().getvalueof("category",foirequestschema.get("category")) openfoirequest.personalAttributes = self._prearepersonalattributes(foirequestschema, userid) openfoirequest.requestApplicants = self.__prepareapplicants(foirequestschema, userid) if foirequestid is not None: @@ -127,10 +127,12 @@ def __prepareapplicants(self, foirequestschema, userid): requestapplicantarr = [] selfalsoknownas=None selfdob=None + selfcategoryid=None if foirequestschema.get("additionalPersonalInfo") is not None and foirequestschema.get('requeststatusid') == 1: applicantinfo = foirequestschema.get("additionalPersonalInfo") selfdob = applicantinfo["birthDate"] if requestservicebuilder().isNotBlankorNone(foirequestschema,"birthDate","additionalPersonalInfo") else None selfalsoknownas = applicantinfo["alsoKnownAs"] if requestservicebuilder().isNotBlankorNone(foirequestschema,"alsoKnownAs","additionalPersonalInfo") else None + selfcategoryid = requestserviceconfigurator().getvalueof("category",foirequestschema.get("category")) if requestservicebuilder().isNotBlankorNone(foirequestschema,"category","main") else None # if foirequestschema.get('foiRequestApplicantID') is None and foirequestschema.get('requeststatusid') == 1: if foirequestschema.get('foiRequestApplicantID') is not None: @@ -147,7 +149,8 @@ def __prepareapplicants(self, foirequestschema, userid): foirequestschema.get("middleName"), foirequestschema.get("businessName"), selfalsoknownas, - selfdob) + selfdob, + selfcategoryid) ) #Prepare additional applicants From b028f3488df861766b90931af6b39f86c0d54d33 Mon Sep 17 00:00:00 2001 From: "sumathi.thirumani" Date: Thu, 18 Jan 2024 14:46:30 -0800 Subject: [PATCH 215/238] Sync from dev. --- request-management-api/request_api/services/events/oipc.py | 6 ++++-- request-management-api/request_api/services/eventservice.py | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/request-management-api/request_api/services/events/oipc.py b/request-management-api/request_api/services/events/oipc.py index a440a1104..df3305dec 100644 --- a/request-management-api/request_api/services/events/oipc.py +++ b/request-management-api/request_api/services/events/oipc.py @@ -18,11 +18,13 @@ class oipcevent: """ FOI OIPC Event management service """ - def createoipcevent(self, requestid, userid): + def createoipcevent(self, requestid, requesttype, userid): + if requesttype != "ministryrequest": + return DefaultMethodResult(True,'No change',requestid) ministryrequest = FOIMinistryRequest.getmetadata(requestid) if ministryrequest["isoipcreview"] in (None, False): notificationservice().dismissnotifications_by_requestid_type(requestid, "ministryrequest", self.__notificationtype()) - return DefaultMethodResult(True,'No change',requestid) + return DefaultMethodResult(True,'Dismiss OIPC events',requestid) inquiryoutcomes = oipcservice().getinquiryoutcomes() version = ministryrequest["version"] curoipcs = FOIRequestOIPC.getoipc(requestid, version) diff --git a/request-management-api/request_api/services/eventservice.py b/request-management-api/request_api/services/eventservice.py index 614cd4351..96ba48dcc 100644 --- a/request-management-api/request_api/services/eventservice.py +++ b/request-management-api/request_api/services/eventservice.py @@ -36,7 +36,7 @@ def posteventsync(self, requestid, requesttype, userid, username, isministryuser stateeventresponse = stateevent().createstatetransitionevent(requestid, requesttype, userid, username) divisioneventresponse = divisionevent().createdivisionevent(requestid, requesttype, userid) assignmentresponse = assignmentevent().createassignmentevent(requestid, requesttype, userid, isministryuser,assigneename,username) - oipcresponse = oipcevent().createoipcevent(requestid, userid) + oipcresponse = oipcevent().createoipcevent(requestid, requesttype, userid) if stateeventresponse.success == False or divisioneventresponse.success == False or assignmentresponse.success == False or oipcresponse.success == False: current_app.logger.error("FOI Notification failed for event for request= %s ; state response=%s ; division response=%s ; assignment response=%s ; oipc response=%s" % (requestid, stateeventresponse.message, divisioneventresponse.message, assignmentresponse.message, oipcresponse.message)) except BusinessException as exception: From c923a955ad3615aa645e2df5c350db2add82ac40 Mon Sep 17 00:00:00 2001 From: sumathi-thirumani-aot <57740789+sumathi-thirumani-aot@users.noreply.github.com> Date: Thu, 18 Jan 2024 09:15:31 -0800 Subject: [PATCH 216/238] Merge commit '59e01ed63a032698ee9859f60ac1527df5b11daf' into test-rook-merge-dev # Conflicts: # notification-manager/common/notificationusertypes.json # request-management-api/common/notificationusertypes.json --- .../common/notificationusertypes.json | 2 +- .../dao/models/NotificationUserTypes.py | 20 +++++++++++ .../notifications/notificationconfig.py | 33 ++++++++++++++----- .../notifications/notificationuser.py | 10 +++--- .../services/notificationservice.py | 8 ++--- .../models/FOIRawRequestNotificationUsers.py | 5 +-- .../request_api/services/events/state.py | 4 ++- 7 files changed, 59 insertions(+), 23 deletions(-) diff --git a/notification-manager/common/notificationusertypes.json b/notification-manager/common/notificationusertypes.json index 3a5185cd9..a0adaa57e 100644 --- a/notification-manager/common/notificationusertypes.json +++ b/notification-manager/common/notificationusertypes.json @@ -25,7 +25,7 @@ }, "comment tagged user": { "name": "comment tagged user", - "notificationusertypelabel": "commentuser" + "notificationusertypelabel": "assignee" }, "triggereduser": { "name": "Triggered User", diff --git a/notification-manager/notification_api/dao/models/NotificationUserTypes.py b/notification-manager/notification_api/dao/models/NotificationUserTypes.py index ae06e67f6..99bd7be46 100644 --- a/notification-manager/notification_api/dao/models/NotificationUserTypes.py +++ b/notification-manager/notification_api/dao/models/NotificationUserTypes.py @@ -26,3 +26,23 @@ def getid(self, name): finally: if conn: conn.close() + + def getidbylabel(self, label): + conn = None + try: + _notificationusertypes = [] + conn = getconnection() + cursor = conn.cursor() + cursor.execute("""select notificationusertypeid from "NotificationUserTypes" nt where isactive = true and notificationusertypelabel = '{0}'""".format(label)) + data = cursor.fetchone() + if data is not None: + data = {"notificationusertypeid": data[0]} + return data + + cursor.close() + return _notificationusertypes + except(Exception) as error: + logging.error(error) + finally: + if conn: + conn.close() diff --git a/notification-manager/notification_api/services/notifications/notificationconfig.py b/notification-manager/notification_api/services/notifications/notificationconfig.py index 6b18da016..215a969b0 100644 --- a/notification-manager/notification_api/services/notifications/notificationconfig.py +++ b/notification-manager/notification_api/services/notifications/notificationconfig.py @@ -5,32 +5,47 @@ import os from notification_api.dao.models.NotificationTypes import NotificationType from notification_api.dao.models.NotificationUserTypes import NotificationUserType +notificationuserfile = open('common/notificationusertypes.json', encoding="utf8") +notificationusertypes_cache = json.load(notificationuserfile) + +notificationfile = open('common/notificationtypes.json', encoding="utf8") +notificationtypes_cache = json.load(notificationfile) class notificationconfig: """ Notfication config """ - - def getnotificationtypeid(self, notificationtype): - notificationid = NotificationType().getid(notificationtype) - if notificationid is not None: - return notificationid - def getnotificationtype(self, notificationtype): notificationid = NotificationType().getid(notificationtype) if notificationid is not None: return notificationid - def getnotificationusertypeid(self, notificationusertype): + def getnotificationusertype(self, notificationusertype): notificationuserid = NotificationUserType().getid(notificationusertype) if notificationuserid is not None: return notificationuserid + - def getnotificationusertype(self, notificationusertype): - notificationuserid = NotificationUserType().getid(notificationusertype) + # This method is used to get the notification user type label + # It first tries to get the notification user type label from the cache + # If it is not found in the cache, it fetches it from the DB + def getnotificationusertypelabel(self, notificationusertype): + notificationusertype_format = notificationusertype.replace(" ", "").lower() + if notificationusertype_format in notificationusertypes_cache: + return notificationusertypes_cache[notificationusertype_format]['notificationusertypelabel'] + else: + print("Notification user type not found in json. Fetching from DB", notificationusertype) + notificationusertypeobj = self.getnotificationusertype(notificationusertype) + if notificationusertypeobj is not None: + return notificationusertypeobj['notificationusertypelabel'] + return None + + def getnotificationusertypeidbylabel(self, label): + notificationuserid = NotificationUserType().getidbylabel(label) if notificationuserid is not None: return notificationuserid + def getnotificationdays(self): if 'FOI_NOTIFICATION_DAYS' in os.environ and os.getenv('FOI_NOTIFICATION_DAYS') != '': return os.getenv('FOI_NOTIFICATION_DAYS') diff --git a/notification-manager/notification_api/services/notifications/notificationuser.py b/notification-manager/notification_api/services/notifications/notificationuser.py index 35341738f..24e99537c 100644 --- a/notification-manager/notification_api/services/notifications/notificationuser.py +++ b/notification-manager/notification_api/services/notifications/notificationuser.py @@ -53,22 +53,24 @@ def __istaggeduser(self, notificationuser, foicomment, notificationtype): def __gettriggereduser(self, userid, notificationtype): notificationusers = [] + notificationtypelabel = "assignee" if notificationtype in ["Records", "PDFStitch"]: - notificationusers.append({"userid":userid, "usertype":notificationconfig().getnotificationusertype("Triggered User")['notificationusertypelabel']}) + notificationusers.append({"userid":userid, "usertype":notificationtypelabel}) return notificationusers def __getwatchers(self, notificationtype, foirequest, requesttype, requestjson=None): notificationusers = [] - if notificationtype == "Watcher": - notificationusers.append({"userid": requestjson['watchedby'], "usertype":notificationconfig().getnotificationusertype("Watcher")['notificationusertypelabel']}) + notificationtypelabel = "watcher" + if notificationtype == "Watcher": + notificationusers.append({"userid": requestjson['watchedby'], "usertype":notificationtypelabel}) else: if requesttype == "ministryrequest": watchers = FOIMinistryRequest().getwatchers(foirequest["foiministryrequestid"]) else: watchers = FOIRawRequest().getwatchers(foirequest['requestid']) for watcher in watchers: - notificationusers.append({"userid":watcher["watchedby"], "usertype":notificationconfig().getnotificationusertype("Watcher")['notificationusertypelabel']}) + notificationusers.append({"userid":watcher["watchedby"], "usertype":notificationtypelabel}) return notificationusers def __getassignees(self, foirequest, requesttype, notificationtype, requestjson=None): diff --git a/notification-manager/notification_api/services/notificationservice.py b/notification-manager/notification_api/services/notificationservice.py index 3a9df645d..aa6fe43fe 100644 --- a/notification-manager/notification_api/services/notificationservice.py +++ b/notification-manager/notification_api/services/notificationservice.py @@ -87,10 +87,10 @@ def __preparenotificationuser(self, notificationid, notificationuser, userid, mu usertype = notificationusertypes_cache[notificationuser["usertype"]] if usertype is None: print('User type not found', notificationuser["usertype"]) - return None - notificationtypes = notificationconfig().getnotificationusertype(usertype['name']) - user.notificationusertypelabel = notificationtypes['notificationusertypelabel'] - user.notificationusertypeid = notificationtypes['notificationusertypeid'] + return None + notificationusertypelabel = notificationconfig().getnotificationusertypelabel(usertype['name']) + user.notificationusertypelabel = notificationusertypelabel + user.notificationusertypeid = notificationconfig().getnotificationusertypeidbylabel(notificationusertypelabel)['notificationusertypeid'] user.notificationid = notificationid user.userid = notificationuser["userid"] user.createdby = userid diff --git a/request-management-api/request_api/models/FOIRawRequestNotificationUsers.py b/request-management-api/request_api/models/FOIRawRequestNotificationUsers.py index 2f114310d..9d3b15523 100644 --- a/request-management-api/request_api/models/FOIRawRequestNotificationUsers.py +++ b/request-management-api/request_api/models/FOIRawRequestNotificationUsers.py @@ -96,10 +96,7 @@ def getnotificationsbyuser(cls, userid): return notifications @classmethod - def getnotificationsbyuserandtype(cls, userid, typeid): - for key in notificationusertypes_cache: - if (notificationusertypes_cache[key].notificationusertypeid == typeid) or (notificationusertypes_cache[key].notificationusertypelabel == typeid): - notificationusertypelabel = notificationusertypes_cache[key].notificationusertypelabel + def getnotificationsbyuserandtype(cls, userid, notificationusertypelabel): notifications = [] try: sql = """select notificationid, count(1) as relcount from "FOIRawRequestNotificationUsers" frnu diff --git a/request-management-api/request_api/services/events/state.py b/request-management-api/request_api/services/events/state.py index 877009889..d5b015d43 100644 --- a/request-management-api/request_api/services/events/state.py +++ b/request-management-api/request_api/services/events/state.py @@ -63,7 +63,6 @@ def __createnotification(self, requestid, state, requesttype, userid): if state == StateName.callforrecords.value and requesttype == "ministryrequest": foirequest = notificationservice().getrequest(requestid, requesttype) _notificationtype = "Group Members" if foirequest['assignedministryperson'] is None else "State" - notificationtype = NotificationType().getnotificationtypeid(_notificationtype) notification = self.__preparenotification(state) if state == StateName.response.value and requesttype == "ministryrequest": signgoffapproval = FOIMinistryRequest().getrequest(requestid)['ministrysignoffapproval'] @@ -74,10 +73,13 @@ def __createnotification(self, requestid, state, requesttype, userid): if state == StateName.archived.value: _openedministries = FOIMinistryRequest.getministriesopenedbyuid(requestid) for ministry in _openedministries: + notificationtype = NotificationType().getnotificationtypeid("State") response = notificationservice().createnotification({"message" : notification}, ministry["ministryrequestid"], 'ministryrequest', notificationtype, userid) else: + notificationtype = NotificationType().getnotificationtypeid("State") response = notificationservice().createnotification({"message" : notification}, requestid, requesttype, notificationtype, userid) if _notificationtype == "Group Members": + notificationtype = NotificationType().getnotificationtypeid(_notificationtype) notification = self.__preparegroupmembernotification(state, requestid) groupmemberresponse = notificationservice().createnotification({"message" : notification}, requestid, requesttype, notificationtype, userid) if response.success == True and groupmemberresponse.success == True : From d89e1be222fa89d6b9aa1f0a72e8f2b9941127de Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 19 Jan 2024 14:16:53 -0800 Subject: [PATCH 217/238] add additional logic to only show profile modal before open state disable state change in intake in progress until after profile has been chosen get latest profile applicant id before saving request to applicant association during transition to open state --- .../components/FOI/FOIAuthenticateRouting.jsx | 2 +- .../FOI/FOIRequest/AddressContanctInfo.js | 13 +++-- .../FOI/FOIRequest/ApplicantProfileModal.js | 47 ++++++++++++++----- .../components/FOI/FOIRequest/FOIRequest.js | 4 +- .../MinistryReview/MinistryReview.js | 2 +- .../FOI/customComponents/StateDropDown.js | 4 +- .../FOI/customComponents/statedropdown.scss | 4 ++ .../models/FOIRequestApplicants.py | 35 ++++++++------ .../request_api/schemas/foiapplicant.py | 1 + .../request_api/services/applicantservice.py | 13 ++--- .../foirequest/requestservicecreate.py | 4 +- 11 files changed, 87 insertions(+), 42 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIAuthenticateRouting.jsx b/forms-flow-web/src/components/FOI/FOIAuthenticateRouting.jsx index 8ad114ee7..5eefd6e29 100644 --- a/forms-flow-web/src/components/FOI/FOIAuthenticateRouting.jsx +++ b/forms-flow-web/src/components/FOI/FOIAuthenticateRouting.jsx @@ -63,7 +63,7 @@ const FOIAuthenticateRouting = React.memo((props) => { - + diff --git a/forms-flow-web/src/components/FOI/FOIRequest/AddressContanctInfo.js b/forms-flow-web/src/components/FOI/FOIRequest/AddressContanctInfo.js index 451b26fc6..60807d59a 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/AddressContanctInfo.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/AddressContanctInfo.js @@ -305,9 +305,16 @@ const AddressContactDetails = memo(
- {moreInfoAction && } + {moreInfoAction && + + } {/* ({ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { const classes = useStyles(); + const isAddRequest = window.location.href.indexOf(FOI_COMPONENT_CONSTANTS.ADDREQUEST) > -1; + let requestDetails = useSelector((state) => state.foiRequests.foiRequestDetail); const dispatch = useDispatch(); @@ -60,13 +62,14 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { const [isLoading, setIsLoading] = useState(true); const [rows, setRows] = useState([]); const [selectedApplicant, setSelectedApplicant] = useState(false) - const [searchMode, setSearchMode] = useState("auto") + const [searchMode, setSearchMode] = useState(isAddRequest ? "manual" : "auto") const [saveApplicantObject, setSaveApplicantObject] = React.useState({}) const [showRequestHistory, setShowRequestHistory] = useState(false); const [confirmationMessage, setConfirmationMessage] = useState(false); const [createConfirmation, setCreateConfirmation] = useState(false); const [isProfileDifferent, setIsProfileDifferent] = useState(false); const [applicantHistory, setApplicantHistory] = useState(false); + const [requestHistory, setRequestHistory] = useState(false); const columns = [ { @@ -129,7 +132,7 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { useEffect(() => { if (modalOpen) { setIsLoading(true); - if (requestDetails.currentState === StateEnum.intakeinprogress.name) { + if (!requestDetails.stateTransition?.filter(s => s.status === StateEnum.open.name).length > 0) { dispatch(fetchPotentialApplicants( requestDetails.firstName, requestDetails.lastName, @@ -142,7 +145,9 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { } else { setSelectedApplicant(true); dispatch(fetchApplicantInfo(requestDetails.foiRequestApplicantID, (err, res) => { - setSelectedApplicant(res); + const {requestHistory, ...selectedApplicant} = res + setSelectedApplicant(selectedApplicant); + setRequestHistory(requestHistory) setIsLoading(false); })) } @@ -152,9 +157,10 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { useEffect(() => { setSaveApplicantObject({...selectedApplicant}) for (let field in selectedApplicant) { + console.log(field) if (field === 'additionalPersonalInfo') { if (requestDetails[field] && requestDetails.requestType === 'personal') { - for (let additionalField in requestDetails[field]) { + for (let additionalField in selectedApplicant[field]) { if (requestDetails[field][additionalField] && selectedApplicant[field][additionalField] !== requestDetails[field][additionalField]) { setIsProfileDifferent(true); break; @@ -182,7 +188,8 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { const selectApplicantRow = (e) => { dispatch(fetchApplicantRequests(e.row.foiRequestApplicantID, (err, res) => { - setSelectedApplicant({...e.row, requestHistory: res}); + setSelectedApplicant(e.row) + setRequestHistory(res); setIsLoading(false); })) } @@ -192,10 +199,14 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { setIsLoading(true); setRows([]); setSelectedApplicant(false); - setConfirmationMessage(false); + setSearchMode(isAddRequest ? "manual" : "auto") + setSaveApplicantObject({}) setShowRequestHistory(false); - setApplicantHistory(false); + setConfirmationMessage(false); setCreateConfirmation(false); + setIsProfileDifferent(false); + setApplicantHistory(false); + setRequestHistory(false); handleModalClose(); } @@ -273,7 +284,7 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { } const selectProfile = () => { - if (_.isEqual(selectedApplicant, saveApplicantObject) || confirmationMessage) { + if (confirmationMessage) { handleClose(); // set loading screen dispatch(setFOILoader(true)); @@ -283,6 +294,9 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { dispatch(setFOIRequestApplicantProfile(saveApplicantObject)); } })); + } else if (_.isEqual(selectedApplicant, saveApplicantObject)) { + handleClose(); + dispatch(setFOIRequestApplicantProfile(saveApplicantObject)); } else { setConfirmationMessage(true); } @@ -314,11 +328,12 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { const back = () => { if (applicantHistory) { setApplicantHistory(false); - } else if (requestDetails.currentState === StateEnum.intakeinprogress.name) { + } else if (requestDetails.stateTransition?.filter(s => s.status === StateEnum.open.name).length > 0) { handleClose(); } else { setSelectedApplicant(false); setShowRequestHistory(false); + setIsProfileDifferent(false); } } @@ -338,6 +353,14 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { } } + const isSaveDisabled = () => { + if (!requestDetails.stateTransition?.filter(s => s.status === StateEnum.open.name).length > 0) { + return isProfileDifferent + } else { + return _.isEqual(selectedApplicant, saveApplicantObject) + } + } + return (
@@ -383,7 +406,7 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { [classes.disabledTitle]: !showRequestHistory })} > - Request History ({selectedApplicant?.requestHistory?.length}) + Request History ({requestHistory?.length}) : @@ -407,7 +430,7 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { { <>{!applicantHistory && } diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index 767c70189..f61135e2e 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -340,7 +340,7 @@ const FOIRequest = React.memo(({ userDetail, openApplicantProfileModal }) => { useEffect(() => { if (requestApplicantProfile) { - if (requestDetails.currentState === StateEnum.intakeinprogress.name) { + if (!ministryId) { let newRequestDetails = { ...saveRequestObject }; for (let field in requestApplicantProfile) { if (field === "additionalPersonalInfo") { @@ -936,7 +936,7 @@ const FOIRequest = React.memo(({ userDetail, openApplicantProfileModal }) => { isMinistryCoordinator={false} isValidationError={isValidationError} requestType={requestDetails?.requestType} - isDivisionalCoordinator={false} + disabled={requestDetails.currentState === StateEnum.intakeinprogress.name && !requestDetails.foiRequestApplicantID} />
diff --git a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js index 6b779db48..db2df4ab3 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js @@ -550,7 +550,7 @@ const MinistryReview = React.memo(({ userDetail }) => { isMinistryCoordinator={true} isValidationError={isValidationError} requestType={requestDetails?.requestType} - isDivisionalCoordinator={IsDivisionalCoordinator()} + disabled={IsDivisionalCoordinator()} /> ); diff --git a/forms-flow-web/src/components/FOI/customComponents/StateDropDown.js b/forms-flow-web/src/components/FOI/customComponents/StateDropDown.js index c2a637b52..bb6fcdbb0 100644 --- a/forms-flow-web/src/components/FOI/customComponents/StateDropDown.js +++ b/forms-flow-web/src/components/FOI/customComponents/StateDropDown.js @@ -21,7 +21,7 @@ const StateDropDown = ({ stateTransition, updateStateDropDown, requestType, - isDivisionalCoordinator, + disabled, }) => { const _isMinistryCoordinator = isMinistryCoordinator; @@ -247,7 +247,7 @@ const StateDropDown = ({ input={} variant="outlined" fullWidth - disabled={isDivisionalCoordinator} + disabled={disabled} > {menuItems} diff --git a/forms-flow-web/src/components/FOI/customComponents/statedropdown.scss b/forms-flow-web/src/components/FOI/customComponents/statedropdown.scss index f38a748e4..90c49b102 100644 --- a/forms-flow-web/src/components/FOI/customComponents/statedropdown.scss +++ b/forms-flow-web/src/components/FOI/customComponents/statedropdown.scss @@ -5,6 +5,10 @@ margin-bottom: 10px; } +#foi-status-dropdown.Mui-disabled { + cursor: not-allowed; +} + .foi-state-dropdown .MuiOutlinedInput-root { color: white !important; } diff --git a/request-management-api/request_api/models/FOIRequestApplicants.py b/request-management-api/request_api/models/FOIRequestApplicants.py index 109d4fadf..aff0b3f5c 100644 --- a/request-management-api/request_api/models/FOIRequestApplicants.py +++ b/request-management-api/request_api/models/FOIRequestApplicants.py @@ -65,24 +65,31 @@ def updateapplicantprofile(cls, foirequestapplicantid, firstname, lastname, midd # applicant.isactive = False applicant_query.update({FOIRequestApplicant.applicantprofileid:str(uuid.uuid4())}) - applicantfromform = FOIRequestApplicant().prepareapplicantforcomparing(firstname, lastname, middlename, businessname, alsoknownas, dob, applicantcategoryid) + applicantfromform = FOIRequestApplicant().prepareapplicantforcomparing(firstname, lastname, middlename, businessname, alsoknownas, datetime.strptime(dob, "%Y-%m-%d"), applicantcategoryid) applicantfromdb = FOIRequestApplicant().prepareapplicantforcomparing(applicant.firstname, applicant.lastname, applicant.middlename, applicant.businessname, applicant.alsoknownas, applicant.dob, applicant.applicantcategoryid) if applicantfromform != applicantfromdb: _applicant = FOIRequestApplicant() _applicant.createdby = userid - _applicant.firstname = applicantfromform.firstname - _applicant.lastname = applicantfromform.lastname - _applicant.middlename = applicantfromform.middlename - _applicant.businessname = applicantfromform.businessname - _applicant.alsoknownas = applicantfromform.alsoknownas - _applicant.dob = applicantfromform.dob + _applicant.firstname = applicantfromform['firstname'] + _applicant.lastname = applicantfromform['lastname'] + _applicant.middlename = applicantfromform['middlename'] + _applicant.businessname = applicantfromform['businessname'] + _applicant.alsoknownas = applicantfromform['alsoknownas'] + _applicant.dob = applicantfromform['dob'] _applicant.applicantprofileid = applicant.applicantprofileid - _applicant.applicantcategoryid = applicantfromform.applicantcategoryid + _applicant.applicantcategoryid = applicantfromform['applicantcategoryid'] db.session.add(_applicant) db.session.commit() return DefaultMethodResult(True,'Applicant profile updated',_applicant.foirequestapplicantid) else: return DefaultMethodResult(True,'No update',applicant.foirequestapplicantid) + + @classmethod + def getlatestprofilebyapplicantid(cls, applicantid): + schema = FOIRequestApplicantSchema(many=False) + sq = db.session.query(FOIRequestApplicant.applicantprofileid).filter_by(foirequestapplicantid=applicantid) + query = db.session.query(FOIRequestApplicant).filter(FOIRequestApplicant.applicantprofileid.in_(sq)).order_by(FOIRequestApplicant.foirequestapplicantid.desc()).first() + return schema.dump(query) # Search applicant by id @classmethod @@ -168,7 +175,7 @@ def getapplicantbyid(cls, applicantid): # ) ).join( ApplicantCategory, - ApplicantCategory.applicantcategoryid == FOIRequest.applicantcategoryid + ApplicantCategory.applicantcategoryid == FOIRequestApplicant.applicantcategoryid ).join( subquery_foirequest_maxversion, and_(*joincondition) @@ -432,7 +439,7 @@ def getapplicantbyemail(cls, email): # ) ).join( ApplicantCategory, - ApplicantCategory.applicantcategoryid == FOIRequest.applicantcategoryid + ApplicantCategory.applicantcategoryid == FOIRequestApplicant.applicantcategoryid ).join( subquery_foirequest_maxversion, and_(*joincondition) @@ -700,7 +707,7 @@ def searchapplicant(cls, keywords): # ) ).join( ApplicantCategory, - ApplicantCategory.applicantcategoryid == FOIRequest.applicantcategoryid + ApplicantCategory.applicantcategoryid == FOIRequestApplicant.applicantcategoryid ).join( subquery_foirequest_maxversion, and_(*joincondition) @@ -1211,14 +1218,14 @@ def prepareapplicantforcomparing(cls, firstname, lastname, middlename, businessn 'middlename': middlename if middlename is not None or middlename != '' else None, 'businessname': businessname if businessname is not None or businessname != '' else None, 'alsoknownas': alsoknownas if alsoknownas is not None or alsoknownas != '' else None, - 'dob': datetime.strptime(dob, "%Y-%m-%d") if dob is not None or dob != '' else None, - 'applicantcategoryid': applicantcategoryid if applicantcategoryid is not None or alsoknownas != 0 else None, + 'dob': dob if dob is not None or dob != '' else None, + 'applicantcategoryid': applicantcategoryid if applicantcategoryid is not None or applicantcategoryid != 0 else None, } class FOIRequestApplicantSchema(ma.Schema): class Meta: - fields = ('foirequestapplicantid','firstname','middlename','lastname','alsoknownas','dob','businessname') + fields = ('foirequestapplicantid','firstname','middlename','lastname','alsoknownas','dob','businessname', 'applicantcategoryid', 'applicantprofileid') class ApplicantProfileSchema(ma.Schema): class Meta: diff --git a/request-management-api/request_api/schemas/foiapplicant.py b/request-management-api/request_api/schemas/foiapplicant.py index cd62b8140..0ab27f44f 100644 --- a/request-management-api/request_api/schemas/foiapplicant.py +++ b/request-management-api/request_api/schemas/foiapplicant.py @@ -13,6 +13,7 @@ class Meta: # pylint: disable=too-few-public-methods lastName = fields.Str(data_key="lastName", required=True,validate=[validate.Length(min=1, error=BLANK_EXCEPTION_MESSAGE, max=50)]) email = fields.Str(data_key="email",allow_none=True, validate=[validate.Length(max=120, error=MAX_EXCEPTION_MESSAGE)]) businessName = fields.Str(data_key="businessName",allow_none=True, validate=[validate.Length(max=255, error=MAX_EXCEPTION_MESSAGE)]) + category = fields.Str(data_key="category", required=True,validate=[validate.Length(min=1, error=BLANK_EXCEPTION_MESSAGE)]) phonePrimary = fields.Str(data_key="phonePrimary",allow_none=True, validate=[validate.Length(max=50, error=MAX_EXCEPTION_MESSAGE)]) workPhonePrimary = fields.Str(data_key="workPhonePrimary",allow_none=True, validate=[validate.Length(max=50, error=MAX_EXCEPTION_MESSAGE)]) diff --git a/request-management-api/request_api/services/applicantservice.py b/request-management-api/request_api/services/applicantservice.py index e9003c739..4929351de 100644 --- a/request-management-api/request_api/services/applicantservice.py +++ b/request-management-api/request_api/services/applicantservice.py @@ -3,6 +3,7 @@ from re import VERBOSE from request_api.models.FOIRequestApplicants import FOIRequestApplicant from request_api.models.FOIMinistryRequests import FOIMinistryRequest +from request_api.models.ApplicantCategories import ApplicantCategory from request_api.services.requestservice import requestservicegetter, requestservicecreate from request_api.auth import AuthHelper from dateutil import tz, parser @@ -29,7 +30,6 @@ def getapplicantbyid(self, applicantid): applicant = FOIRequestApplicant.getapplicantbyid(applicantid) applicant = self.__prepareapplicant(applicant) applicant['requestHistory'] = self.getapplicantrequests(applicantid) - applicant.pop('requestType') return applicant def searchapplicant(self, keywords): @@ -42,6 +42,7 @@ def searchapplicant(self, keywords): return applicantqueue def saveapplicantinfo(self, applicantschema, userid): + categoryid = ApplicantCategory().getapplicantcategory(applicantschema['category'])["applicantcategoryid"] applicant = FOIRequestApplicant.updateapplicantprofile( applicantschema['foiRequestApplicantID'], applicantschema['firstName'], @@ -50,7 +51,7 @@ def saveapplicantinfo(self, applicantschema, userid): applicantschema['businessName'], applicantschema.get('additionalPersonalInfo', None).get('alsoKnownAs', None), applicantschema.get('additionalPersonalInfo', None).get('birthDate', None), - applicantschema['applicantCategoryID'], + categoryid, userid ) # replace with applicant id once new save function is written requests = FOIMinistryRequest.getopenrequestsbyrequestId(applicantschema['foirequestID']) @@ -92,10 +93,10 @@ def __prepareapplicant(self, applicant): #'createdat' : self.__formatedate(applicant["createdat)"], 'businessName': self.__first_not_null(applicant["businessname"]), # 'applicant': applicant["applicant"], - 'foirequestID': applicant["foirequestid"], - 'foirequestVersion': applicant["foirequestversion"], - 'requestType': applicant["requesttype"], - 'category': applicant["applicantcategory"], + # 'foirequestID': applicant["foirequestid"], + # 'foirequestVersion': applicant["foirequestversion"], + # 'requestType': applicant["requesttype"], + 'category': self.__first_not_null(applicant["applicantcategory"]), 'email': self.__first_not_null(applicant["email"]), 'address': self.__first_not_null(applicant["address"]), 'city': self.__first_not_null(applicant["city"]), diff --git a/request-management-api/request_api/services/foirequest/requestservicecreate.py b/request-management-api/request_api/services/foirequest/requestservicecreate.py index f1689010b..196fb01ec 100644 --- a/request-management-api/request_api/services/foirequest/requestservicecreate.py +++ b/request-management-api/request_api/services/foirequest/requestservicecreate.py @@ -12,6 +12,7 @@ from request_api.models.FOIRequestContactInformation import FOIRequestContactInformation from request_api.models.FOIRequestPersonalAttributes import FOIRequestPersonalAttribute from request_api.models.FOIRequestApplicantMappings import FOIRequestApplicantMapping +from request_api.models.FOIRequestApplicants import FOIRequestApplicant from request_api.models.RequestorType import RequestorType import json @@ -134,8 +135,9 @@ def __prepareapplicants(self, foirequestschema, userid): # if foirequestschema.get('foiRequestApplicantID') is None and foirequestschema.get('requeststatusid') == 1: if foirequestschema.get('foiRequestApplicantID') is not None: + applicant = FOIRequestApplicant().getlatestprofilebyapplicantid(foirequestschema['foiRequestApplicantID']) requestapplicant = FOIRequestApplicantMapping() - requestapplicant.foirequestapplicantid = foirequestschema['foiRequestApplicantID'] + requestapplicant.foirequestapplicantid = applicant['foirequestapplicantid'] requestapplicant.requestortypeid = RequestorType().getrequestortype("Self")["requestortypeid"] requestapplicantarr.append(requestapplicant) else: From 0a5826528b93af53b008a1f47755f3541ca50908 Mon Sep 17 00:00:00 2001 From: Richard Qi Date: Fri, 19 Jan 2024 16:07:06 -0800 Subject: [PATCH 218/238] 1. categoryid in applicant table 2. get request by applicantid --- .../ba218164248e_add_category_to_applicant.py | 17 +++++++++++++ .../request_api/models/FOIMinistryRequests.py | 25 +++++++++++++++---- .../models/FOIRequestApplicantMappings.py | 4 +-- .../models/FOIRequestApplicants.py | 14 ++++++----- .../request_api/models/FOIRequests.py | 7 +++--- .../request_api/schemas/foiapplicant.py | 5 +--- .../request_api/schemas/foirequest.py | 11 ++++---- .../request_api/services/applicantservice.py | 8 ++++-- .../foirequest/requestservicecreate.py | 4 ++- .../foirequest/requestservicegetter.py | 21 +++++++++++----- .../requestserviceministrybuilder.py | 2 +- 11 files changed, 82 insertions(+), 36 deletions(-) diff --git a/request-management-api/migrations/versions/ba218164248e_add_category_to_applicant.py b/request-management-api/migrations/versions/ba218164248e_add_category_to_applicant.py index 007bec8a4..1c474582c 100644 --- a/request-management-api/migrations/versions/ba218164248e_add_category_to_applicant.py +++ b/request-management-api/migrations/versions/ba218164248e_add_category_to_applicant.py @@ -19,10 +19,27 @@ def upgrade(): # ### commands auto generated by Alembic - please adjust! ### op.add_column('FOIRequestApplicants', sa.Column('applicantcategoryid', sa.Integer(), nullable=True)) + op.create_foreign_key(None, 'FOIRequestApplicants', 'ApplicantCategories', ['applicantcategoryid'], ['applicantcategoryid']) + + op.execute( + ''' + UPDATE public."FOIRequestApplicants" + set applicantcategoryid = subquery.applicantcategoryid + from ( + select public."FOIRequestApplicantMappings".foirequestapplicantid, public."FOIRequests".applicantcategoryid + from public."FOIRequestApplicantMappings" + join public."FOIRequests" on public."FOIRequests".foirequestid = public."FOIRequestApplicantMappings".foirequest_id and public."FOIRequests".version = public."FOIRequestApplicantMappings".foirequestversion_id + group by public."FOIRequestApplicantMappings".foirequestapplicantid, public."FOIRequests".applicantcategoryid + ) as subquery + where public."FOIRequestApplicants".foirequestapplicantid = subquery.foirequestapplicantid + ''' + ) + # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### + op.drop_constraint(None, 'FOIRequestApplicants', type_='foreignkey') op.drop_column('FOIRequestApplicants', 'applicantcategoryid') # ### end Alembic commands ### \ No newline at end of file diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index 2f10afbf2..4a95cd121 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -177,6 +177,7 @@ def getrequests(cls, group = None): ministryrequest =ministryrequest_schema.dump(_session.query(FOIMinistryRequest).filter(FOIMinistryRequest.foiministryrequestid == _requestid).order_by(FOIMinistryRequest.version.desc()).first()) parentrequest = _session.query(FOIRequest).filter(FOIRequest.foirequestid == ministryrequest['foirequest_id'] and FOIRequest.version == ministryrequest['foirequestversion_id']).order_by(FOIRequest.version.desc()).first() requestapplicants = FOIRequestApplicantMapping.getrequestapplicants(ministryrequest['foirequest_id'],ministryrequest['foirequestversion_id']) + print("requestapplicants", requestapplicants) _receiveddate = parentrequest.receiveddate _request["firstName"] = requestapplicants[0]['foirequestapplicant.firstname'] _request["lastName"] = requestapplicants[0]['foirequestapplicant.lastname'] @@ -198,7 +199,8 @@ def getrequests(cls, group = None): _request["version"] = ministryrequest['version'] _request["id"] = parentrequest.foirequestid _request["ministryrequestid"] = ministryrequest['foiministryrequestid'] - _request["applicantcategory"]=parentrequest.applicantcategory.name + # _request["applicantcategory"]=parentrequest.applicantcategory.name + _request["applicantcategory"]=requestapplicants[0]['foirequestapplicant.applicantcategory.name'] _request["identityverified"] = ministryrequest['identityverified'] _requests.append(_request) @@ -233,7 +235,17 @@ def getopenrequestsbyrequestId(cls,requestids): @classmethod def getopenrequestsbyapplicantid(cls,applicantid): + _session = db.session + selectedcolumns = [FOIMinistryRequest.foirequest_id, FOIMinistryRequest.foiministryrequestid] + + #subquery for getting latest version & proper group/team for FOIMinistryRequest + subquery_applicant_maxid = _session.query(FOIRequestApplicant.applicantprofileid, func.max(FOIRequestApplicant.foirequestapplicantid).label('max_id')).group_by(FOIRequestApplicant.applicantprofileid).subquery() + joincondition_applicant = [ + subquery_applicant_maxid.c.applicantprofileid == FOIRequestApplicant.applicantprofileid, + subquery_applicant_maxid.c.max_id == FOIRequestApplicantMapping.foirequestapplicantid, + ] + query = db.session.query( *selectedcolumns ).distinct( @@ -246,9 +258,12 @@ def getopenrequestsbyapplicantid(cls,applicantid): FOIRequestApplicantMapping.requestortypeid == RequestorType['applicant'].value) ).join( FOIRequestApplicant, - FOIRequestApplicant.foirequestapplicantid == FOIRequestApplicantMapping.foirequestapplicantid, - ).filter( FOIRequestApplicant.foirequestapplicantid == applicantid, + ).join( + subquery_applicant_maxid, + and_(*joincondition_applicant) + ).filter( + # FOIRequestApplicant.foirequestapplicantid == applicantid, FOIMinistryRequest.requeststatusid != 3 ).order_by( FOIMinistryRequest.foiministryrequestid.asc(), @@ -552,7 +567,7 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us isouter=True ).join( ApplicantCategory, - and_(ApplicantCategory.applicantcategoryid == FOIRequest.applicantcategoryid, ApplicantCategory.isactive == True) + and_(ApplicantCategory.applicantcategoryid == FOIRequestApplicant.applicantcategoryid, ApplicantCategory.isactive == True) ).join( ProgramArea, FOIMinistryRequest.programareaid == ProgramArea.programareaid @@ -1071,7 +1086,7 @@ def getbasequery(cls, iaoassignee, ministryassignee, userid=None, requestby='IAO isouter=True ).join( ApplicantCategory, - and_(ApplicantCategory.applicantcategoryid == FOIRequest.applicantcategoryid, ApplicantCategory.isactive == True) + and_(ApplicantCategory.applicantcategoryid == FOIRequestApplicant.applicantcategoryid, ApplicantCategory.isactive == True) ).join( ProgramArea, FOIMinistryRequest.programareaid == ProgramArea.programareaid diff --git a/request-management-api/request_api/models/FOIRequestApplicantMappings.py b/request-management-api/request_api/models/FOIRequestApplicantMappings.py index 74cdeef90..7313e1f1a 100644 --- a/request-management-api/request_api/models/FOIRequestApplicantMappings.py +++ b/request-management-api/request_api/models/FOIRequestApplicantMappings.py @@ -44,10 +44,10 @@ def getrequestapplicants(cls,foirequest_id,foirequestversion): FOIRequestApplicantMapping.foirequest_id == foirequest_id, FOIRequestApplicantMapping.foirequestversion_id == foirequestversion ).order_by(FOIRequestApplicantMapping.foirequestapplicantmappingid.asc()).all() - applicantinfos = requestapplicant_schema.dump(_applicantinfos) + applicantinfos = requestapplicant_schema.dump(_applicantinfos) return applicantinfos class FOIRequestApplicantMappingSchema(ma.Schema): class Meta: - fields = ('foirequestapplicantmappingid','foirequest.foirequestid','foirequest.version','requestortype.requestortypeid','requestortype.name','foirequestapplicant.foirequestapplicantid','foirequestapplicant.firstname','foirequestapplicant.lastname','foirequestapplicant.middlename','foirequestapplicant.alsoknownas','foirequestapplicant.dob','foirequestapplicant.businessname') + fields = ('foirequestapplicantmappingid','foirequest.foirequestid','foirequest.version','requestortype.requestortypeid','requestortype.name','foirequestapplicant.foirequestapplicantid','foirequestapplicant.firstname','foirequestapplicant.lastname','foirequestapplicant.middlename','foirequestapplicant.alsoknownas','foirequestapplicant.dob','foirequestapplicant.businessname','foirequestapplicant.applicantcategory.applicantcategoryid','foirequestapplicant.applicantcategory.name') \ No newline at end of file diff --git a/request-management-api/request_api/models/FOIRequestApplicants.py b/request-management-api/request_api/models/FOIRequestApplicants.py index 12e388acc..8d8890b63 100644 --- a/request-management-api/request_api/models/FOIRequestApplicants.py +++ b/request-management-api/request_api/models/FOIRequestApplicants.py @@ -26,7 +26,9 @@ class FOIRequestApplicant(db.Model): alsoknownas = db.Column(db.String(50), unique=False, nullable=True) dob = db.Column(db.DateTime, unique=False, nullable=True) businessname = db.Column(db.String(255), unique=False, nullable=True) - applicantcategoryid = db.Column(db.Integer, unique=False, nullable=True) + # applicantcategoryid = db.Column(db.Integer, unique=False, nullable=True) + applicantcategoryid = db.Column(db.Integer, ForeignKey('ApplicantCategories.applicantcategoryid'), nullable=True) + applicantcategory = relationship("ApplicantCategory", backref=backref("ApplicantCategories"), uselist=False) created_at = db.Column(db.DateTime, default=datetime.now) updated_at = db.Column(db.DateTime, nullable=True) @@ -169,7 +171,7 @@ def getapplicantbyid(cls, applicantid): # ) ).join( ApplicantCategory, - ApplicantCategory.applicantcategoryid == FOIRequest.applicantcategoryid + ApplicantCategory.applicantcategoryid == FOIRequestApplicant.applicantcategoryid ).join( subquery_foirequest_maxversion, and_(*joincondition) @@ -433,7 +435,7 @@ def getapplicantbyemail(cls, email): # ) ).join( ApplicantCategory, - ApplicantCategory.applicantcategoryid == FOIRequest.applicantcategoryid + ApplicantCategory.applicantcategoryid == FOIRequestApplicant.applicantcategoryid ).join( subquery_foirequest_maxversion, and_(*joincondition) @@ -701,7 +703,7 @@ def searchapplicant(cls, keywords): # ) ).join( ApplicantCategory, - ApplicantCategory.applicantcategoryid == FOIRequest.applicantcategoryid + ApplicantCategory.applicantcategoryid == FOIRequestApplicant.applicantcategoryid ).join( subquery_foirequest_maxversion, and_(*joincondition) @@ -996,7 +998,7 @@ def getapplicanthistory(cls, applicantid): FOIRequest.version == FOIRequestApplicantMapping.foirequestversion_id) ).join( ApplicantCategory, - ApplicantCategory.applicantcategoryid == FOIRequest.applicantcategoryid + ApplicantCategory.applicantcategoryid == FOIRequestApplicant.applicantcategoryid ).join( contactemail, and_( @@ -1219,7 +1221,7 @@ def prepareapplicantforcomparing(cls, firstname, lastname, middlename, businessn class FOIRequestApplicantSchema(ma.Schema): class Meta: - fields = ('foirequestapplicantid','firstname','middlename','lastname','alsoknownas','dob','businessname') + fields = ('foirequestapplicantid','firstname','middlename','lastname','alsoknownas','dob','businessname','applicantcategory.applicantcategoryid','applicantcategory.name') class ApplicantProfileSchema(ma.Schema): class Meta: diff --git a/request-management-api/request_api/models/FOIRequests.py b/request-management-api/request_api/models/FOIRequests.py index fcd9ea81a..b84aacf6a 100644 --- a/request-management-api/request_api/models/FOIRequests.py +++ b/request-management-api/request_api/models/FOIRequests.py @@ -32,8 +32,8 @@ class FOIRequest(db.Model): #ForeignKey References - applicantcategoryid = db.Column(db.Integer,ForeignKey('ApplicantCategories.applicantcategoryid')) - applicantcategory = relationship("ApplicantCategory",backref=backref("ApplicantCategories"),uselist=False) + # applicantcategoryid = db.Column(db.Integer,ForeignKey('ApplicantCategories.applicantcategoryid')) + # applicantcategory = relationship("ApplicantCategory",backref=backref("ApplicantCategories"),uselist=False) deliverymodeid = db.Column(db.Integer,ForeignKey('DeliveryModes.deliverymodeid')) deliverymode = relationship("DeliveryMode",backref=backref("DeliveryModes"),uselist=False) @@ -121,6 +121,5 @@ class FOIRequestsSchema(ma.Schema): class Meta: fields = ('foirequestid','version','foirawrequestid','requesttype','receiveddate','initialdescription', 'initialrecordSearchFromDate','initialrecordsearchtodate','receivedmode.receivedmodeid', - 'deliverymode.deliverymodeid','receivedmode.name','deliverymode.name', - 'applicantcategory.applicantcategoryid','applicantcategory.name','wfinstanceid','ministryRequests') + 'deliverymode.deliverymodeid','receivedmode.name','deliverymode.name','wfinstanceid','ministryRequests') \ No newline at end of file diff --git a/request-management-api/request_api/schemas/foiapplicant.py b/request-management-api/request_api/schemas/foiapplicant.py index cd62b8140..4d7f10b60 100644 --- a/request-management-api/request_api/schemas/foiapplicant.py +++ b/request-management-api/request_api/schemas/foiapplicant.py @@ -28,9 +28,6 @@ class Meta: # pylint: disable=too-few-public-methods # publicServiceEmployeeNumber = fields.Str(data_key="publicServiceEmployeeNumber",allow_none=True, validate=[validate.Length(max=50, error=MAX_EXCEPTION_MESSAGE)]) foiRequestApplicantID = fields.Int(data_key="foiRequestApplicantID",required=False,allow_none=True) - foirequestID = fields.List(fields.Int(),data_key="foirequestID",required=True,allow_none=False) - additionalPersonalInfo = fields.Nested(FOIAdditionallPersonalInfoWrapperSchema,required=False,allow_none=True) - - \ No newline at end of file + applicantCategoryID = fields.Int(data_key="applicantCategoryID",required=False,allow_none=True) \ No newline at end of file diff --git a/request-management-api/request_api/schemas/foirequest.py b/request-management-api/request_api/schemas/foirequest.py index 239f320db..e96c4d2c0 100644 --- a/request-management-api/request_api/schemas/foirequest.py +++ b/request-management-api/request_api/schemas/foirequest.py @@ -47,11 +47,12 @@ class Meta: # pylint: disable=too-few-public-methods unknown = EXCLUDE firstname = fields.Str(data_key="firstName") - middlename = fields.Str(data_key="middleName") - lastname = fields.Str(data_key="lastName") - alsoknownas = fields.Str(data_key="alsoKnownAs") - dob = fields.Date(data_key="dob") - businessname = fields.Str(data_key="businessName") + middlename = fields.Str(data_key="middleName") + lastname = fields.Str(data_key="lastName") + alsoknownas = fields.Str(data_key="alsoKnownAs") + dob = fields.Date(data_key="dob") + businessname = fields.Str(data_key="businessName") + applicantcategoryid = fields.Int(data_key="applicantCategoryID") class FOIRequestApplicantSchema(Schema): class Meta: # pylint: disable=too-few-public-methods diff --git a/request-management-api/request_api/services/applicantservice.py b/request-management-api/request_api/services/applicantservice.py index e9003c739..510b90400 100644 --- a/request-management-api/request_api/services/applicantservice.py +++ b/request-management-api/request_api/services/applicantservice.py @@ -11,6 +11,7 @@ from request_api.utils.commons.datetimehandler import datetimehandler from request_api.models.default_method_result import DefaultMethodResult import re +from request_api.services.foirequest.requestserviceconfigurator import requestserviceconfigurator class applicantservice: """ FOI Event Dashboard @@ -42,6 +43,7 @@ def searchapplicant(self, keywords): return applicantqueue def saveapplicantinfo(self, applicantschema, userid): + print("applicantschema", applicantschema) applicant = FOIRequestApplicant.updateapplicantprofile( applicantschema['foiRequestApplicantID'], applicantschema['firstName'], @@ -50,10 +52,12 @@ def saveapplicantinfo(self, applicantschema, userid): applicantschema['businessName'], applicantschema.get('additionalPersonalInfo', None).get('alsoKnownAs', None), applicantschema.get('additionalPersonalInfo', None).get('birthDate', None), - applicantschema['applicantCategoryID'], + requestserviceconfigurator().getvalueof("category",applicantschema['category']), userid ) # replace with applicant id once new save function is written - requests = FOIMinistryRequest.getopenrequestsbyrequestId(applicantschema['foirequestID']) + # requests = FOIMinistryRequest.getopenrequestsbyrequestId(applicantschema['foirequestID']) + requests = FOIMinistryRequest.getopenrequestsbyapplicantid(applicantschema['foiRequestApplicantID']) + print("requests", requests) applicantschema['foiRequestApplicantID'] = applicant.identifier # requests = FOIMinistryRequest.getopenrequestsbyapplicantid(applicantschema['foiRequestApplicantID']) for request in requests: diff --git a/request-management-api/request_api/services/foirequest/requestservicecreate.py b/request-management-api/request_api/services/foirequest/requestservicecreate.py index 1a7cb8a2f..72713938a 100644 --- a/request-management-api/request_api/services/foirequest/requestservicecreate.py +++ b/request-management-api/request_api/services/foirequest/requestservicecreate.py @@ -7,7 +7,7 @@ from request_api.services.watcherservice import watcherservice from request_api.services.foirequest.requestservicebuilder import requestservicebuilder from request_api.services.foirequest.requestserviceministrybuilder import requestserviceministrybuilder -from request_api.services.foirequest.requestserviceconfigurator import requestserviceconfigurator +from request_api.services.foirequest.requestserviceconfigurator import requestserviceconfigurator from request_api.models.PersonalInformationAttributes import PersonalInformationAttribute from request_api.models.FOIRequestContactInformation import FOIRequestContactInformation from request_api.models.FOIRequestPersonalAttributes import FOIRequestPersonalAttribute @@ -128,11 +128,13 @@ def __prepareapplicants(self, foirequestschema, userid): selfalsoknownas=None selfdob=None selfcategoryid=None + print("foirequestschema", foirequestschema) if foirequestschema.get("additionalPersonalInfo") is not None and foirequestschema.get('requeststatusid') == 1: applicantinfo = foirequestschema.get("additionalPersonalInfo") selfdob = applicantinfo["birthDate"] if requestservicebuilder().isNotBlankorNone(foirequestschema,"birthDate","additionalPersonalInfo") else None selfalsoknownas = applicantinfo["alsoKnownAs"] if requestservicebuilder().isNotBlankorNone(foirequestschema,"alsoKnownAs","additionalPersonalInfo") else None selfcategoryid = requestserviceconfigurator().getvalueof("category",foirequestschema.get("category")) if requestservicebuilder().isNotBlankorNone(foirequestschema,"category","main") else None + print("selfcategoryid", selfcategoryid) # if foirequestschema.get('foiRequestApplicantID') is None and foirequestschema.get('requeststatusid') == 1: if foirequestschema.get('foiRequestApplicantID') is not None: diff --git a/request-management-api/request_api/services/foirequest/requestservicegetter.py b/request-management-api/request_api/services/foirequest/requestservicegetter.py index aea1580d4..ee3add1a0 100644 --- a/request-management-api/request_api/services/foirequest/requestservicegetter.py +++ b/request-management-api/request_api/services/foirequest/requestservicegetter.py @@ -47,8 +47,11 @@ def getrequest(self,foirequestid,foiministryrequestid): alsoknownas = applicant['foirequestapplicant.alsoknownas'] foirequestapplicantid = applicant['foirequestapplicant.foirequestapplicantid'] requestortypeid = applicant['requestortype.requestortypeid'] + categoryid = applicant['foirequestapplicant.applicantcategory.applicantcategoryid'] + category = applicant['foirequestapplicant.applicantcategory.name'] + if requestortypeid == 1: - baserequestinfo.update(self.__prepareapplicant(foirequestapplicantid, firstname, middlename, lastname, businessname)) + baserequestinfo.update(self.__prepareapplicant(foirequestapplicantid, firstname, middlename, lastname, businessname, categoryid, category)) additionalpersonalinfo.update(self.__prepareadditionalpersonalinfo(requestortypeid, firstname, middlename, lastname, dob, alsoknownas)) baserequestdetails, additionalpersonalinfodetails = self.preparepersonalattributes(foirequestid, request['version']) @@ -94,8 +97,12 @@ def getrequestdetailsforministry(self,foirequestid,foiministryrequestid, authmem dob = parse(dobraw).strftime(self.__genericdateformat()) if dobraw is not None else '' foirequestapplicantid = applicant['foirequestapplicant.foirequestapplicantid'] requestortypeid = applicant['requestortype.requestortypeid'] + categoryid = applicant['foirequestapplicant.applicantcategory.applicantcategoryid'] + category = applicant['foirequestapplicant.applicantcategory.name'] + businessname = None + if requestortypeid == 1: - baserequestinfo.update(self.__prepareapplicant(foirequestapplicantid, firstname, middlename, lastname)) + baserequestinfo.update(self.__prepareapplicant(foirequestapplicantid, firstname, middlename, lastname, businessname, categoryid, category)) additionalpersonalinfo.update(self.__prepareadditionalpersonalinfo(requestortypeid, firstname, middlename, lastname, dob)) baserequestdetails, additionalpersonalinfodetails = self.preparepersonalattributes(foirequestid, request['version']) baserequestinfo.update(baserequestdetails) @@ -161,8 +168,8 @@ def __preparebaseinfo(self,request,foiministryrequestid,requestministry,requestm 'originalDueDate': parse(requestministry['originalldd']).strftime(self.__genericdateformat()) if requestministry['originalldd'] is not None else parse(requestministry['duedate']).strftime(self.__genericdateformat()), 'programareaid':requestministry['programarea.programareaid'], 'bcgovcode':requestministry['programarea.bcgovcode'], - 'category':request['applicantcategory.name'], - 'categoryid':request['applicantcategory.applicantcategoryid'], + # 'category':'', + # 'categoryid':0, 'assignedministrygroup':requestministry["assignedministrygroup"], 'assignedministryperson':requestministry["assignedministryperson"], 'selectedMinistries':[{'code':requestministry['programarea.bcgovcode'],'id':requestministry['foiministryrequestid'],'name':requestministry['programarea.name'],'selected':'true'}], @@ -229,13 +236,15 @@ def getministryrequest(self, foiministryrequestid): def __genericdateformat(self): return '%Y-%m-%d' - def __prepareapplicant(self, foirequestapplicantid=None, firstname= None, middlename= None, lastname= None, businessname= None): + def __prepareapplicant(self, foirequestapplicantid=None, firstname=None, middlename=None, lastname=None, businessname=None, applicantcategoryid=None, applicantcategory=None): return { 'firstName': firstname, 'middleName': middlename, 'lastName': lastname, 'businessName': businessname, - 'foiRequestApplicantID': foirequestapplicantid + 'foiRequestApplicantID': foirequestapplicantid, + 'categoryid': applicantcategoryid, + 'category': applicantcategory } def __prepareadditionalpersonalinfo(self, requestortypeid, firstname= None, middlename= None, lastname= None, dob= None, alsoknownas= None): diff --git a/request-management-api/request_api/services/foirequest/requestserviceministrybuilder.py b/request-management-api/request_api/services/foirequest/requestserviceministrybuilder.py index f35af8e74..7928588b7 100644 --- a/request-management-api/request_api/services/foirequest/requestserviceministrybuilder.py +++ b/request-management-api/request_api/services/foirequest/requestserviceministrybuilder.py @@ -29,7 +29,7 @@ def createfoirequestfromobject(self, foiobject, userid): foirequest.receiveddate = foiobject['receiveddate'] if 'receiveddate' in foiobject else None foirequest.requesttype = foiobject['requesttype'] foirequest.wfinstanceid = foiobject['wfinstanceid'] - foirequest.applicantcategoryid = foiobject["applicantcategory.applicantcategoryid"] + # foirequest.applicantcategoryid = foiobject["applicantcategory.applicantcategoryid"] foirequest.deliverymodeid = foiobject["deliverymode.deliverymodeid"] foirequest.receivedmodeid = foiobject["receivedmode.receivedmodeid"] foirequest.createdby = userid From 351d8ac38261b4212c54550358609fd39b283d30 Mon Sep 17 00:00:00 2001 From: Richard Qi Date: Fri, 19 Jan 2024 16:46:09 -0800 Subject: [PATCH 219/238] bug fix --- .../request_api/models/FOIRequestApplicants.py | 4 ++-- request-management-api/request_api/schemas/foiapplicant.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/request-management-api/request_api/models/FOIRequestApplicants.py b/request-management-api/request_api/models/FOIRequestApplicants.py index e62b12e42..f2c715717 100644 --- a/request-management-api/request_api/models/FOIRequestApplicants.py +++ b/request-management-api/request_api/models/FOIRequestApplicants.py @@ -68,7 +68,7 @@ def updateapplicantprofile(cls, foirequestapplicantid, firstname, lastname, midd # applicant.isactive = False applicant_query.update({FOIRequestApplicant.applicantprofileid:str(uuid.uuid4())}) - applicantfromform = FOIRequestApplicant().prepareapplicantforcomparing(firstname, lastname, middlename, businessname, alsoknownas, datetime.strptime(dob, "%Y-%m-%d"), applicantcategoryid) + applicantfromform = FOIRequestApplicant().prepareapplicantforcomparing(firstname, lastname, middlename, businessname, alsoknownas, dob, applicantcategoryid) applicantfromdb = FOIRequestApplicant().prepareapplicantforcomparing(applicant.firstname, applicant.lastname, applicant.middlename, applicant.businessname, applicant.alsoknownas, applicant.dob, applicant.applicantcategoryid) if applicantfromform != applicantfromdb: _applicant = FOIRequestApplicant() @@ -1221,7 +1221,7 @@ def prepareapplicantforcomparing(cls, firstname, lastname, middlename, businessn 'middlename': middlename if middlename is not None or middlename != '' else None, 'businessname': businessname if businessname is not None or businessname != '' else None, 'alsoknownas': alsoknownas if alsoknownas is not None or alsoknownas != '' else None, - 'dob': dob if dob is not None or dob != '' else None, + 'dob': datetime.strptime(dob, "%Y-%m-%d") if dob is not None and dob != '' else None, 'applicantcategoryid': applicantcategoryid if applicantcategoryid is not None or applicantcategoryid != 0 else None, } diff --git a/request-management-api/request_api/schemas/foiapplicant.py b/request-management-api/request_api/schemas/foiapplicant.py index f420b07cb..1eeef1292 100644 --- a/request-management-api/request_api/schemas/foiapplicant.py +++ b/request-management-api/request_api/schemas/foiapplicant.py @@ -29,6 +29,6 @@ class Meta: # pylint: disable=too-few-public-methods # publicServiceEmployeeNumber = fields.Str(data_key="publicServiceEmployeeNumber",allow_none=True, validate=[validate.Length(max=50, error=MAX_EXCEPTION_MESSAGE)]) foiRequestApplicantID = fields.Int(data_key="foiRequestApplicantID",required=False,allow_none=True) - foirequestID = fields.List(fields.Int(),data_key="foirequestID",required=True,allow_none=False) + foirequestID = fields.List(fields.Int(),data_key="foirequestID",required=False,allow_none=False) additionalPersonalInfo = fields.Nested(FOIAdditionallPersonalInfoWrapperSchema,required=False,allow_none=True) applicantCategoryID = fields.Int(data_key="applicantCategoryID",required=False,allow_none=True) \ No newline at end of file From 4bef1a2e577160ddacb30bf23acbd776e640f5bb Mon Sep 17 00:00:00 2001 From: Richard Qi Date: Fri, 19 Jan 2024 16:56:35 -0800 Subject: [PATCH 220/238] bug fix --- .../request_api/models/FOIMinistryRequests.py | 1 - request-management-api/request_api/schemas/foiapplicant.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index 4a95cd121..3233f4716 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -177,7 +177,6 @@ def getrequests(cls, group = None): ministryrequest =ministryrequest_schema.dump(_session.query(FOIMinistryRequest).filter(FOIMinistryRequest.foiministryrequestid == _requestid).order_by(FOIMinistryRequest.version.desc()).first()) parentrequest = _session.query(FOIRequest).filter(FOIRequest.foirequestid == ministryrequest['foirequest_id'] and FOIRequest.version == ministryrequest['foirequestversion_id']).order_by(FOIRequest.version.desc()).first() requestapplicants = FOIRequestApplicantMapping.getrequestapplicants(ministryrequest['foirequest_id'],ministryrequest['foirequestversion_id']) - print("requestapplicants", requestapplicants) _receiveddate = parentrequest.receiveddate _request["firstName"] = requestapplicants[0]['foirequestapplicant.firstname'] _request["lastName"] = requestapplicants[0]['foirequestapplicant.lastname'] diff --git a/request-management-api/request_api/schemas/foiapplicant.py b/request-management-api/request_api/schemas/foiapplicant.py index 1eeef1292..a54c62dd1 100644 --- a/request-management-api/request_api/schemas/foiapplicant.py +++ b/request-management-api/request_api/schemas/foiapplicant.py @@ -31,4 +31,4 @@ class Meta: # pylint: disable=too-few-public-methods foiRequestApplicantID = fields.Int(data_key="foiRequestApplicantID",required=False,allow_none=True) foirequestID = fields.List(fields.Int(),data_key="foirequestID",required=False,allow_none=False) additionalPersonalInfo = fields.Nested(FOIAdditionallPersonalInfoWrapperSchema,required=False,allow_none=True) - applicantCategoryID = fields.Int(data_key="applicantCategoryID",required=False,allow_none=True) \ No newline at end of file + category = fields.Int(data_key="category",required=False,allow_none=True) \ No newline at end of file From d1684e9ce0f2892fc0c069b3ddbc502a9df4646f Mon Sep 17 00:00:00 2001 From: Richard Qi Date: Fri, 19 Jan 2024 16:58:06 -0800 Subject: [PATCH 221/238] remove debug code --- request-management-api/request_api/services/applicantservice.py | 1 - .../request_api/services/foirequest/requestservicecreate.py | 2 -- 2 files changed, 3 deletions(-) diff --git a/request-management-api/request_api/services/applicantservice.py b/request-management-api/request_api/services/applicantservice.py index 155fb2855..dae384165 100644 --- a/request-management-api/request_api/services/applicantservice.py +++ b/request-management-api/request_api/services/applicantservice.py @@ -56,7 +56,6 @@ def saveapplicantinfo(self, applicantschema, userid): ) # replace with applicant id once new save function is written # requests = FOIMinistryRequest.getopenrequestsbyrequestId(applicantschema['foirequestID']) requests = FOIMinistryRequest.getopenrequestsbyapplicantid(applicantschema['foiRequestApplicantID']) - print("requests", requests) applicantschema['foiRequestApplicantID'] = applicant.identifier # requests = FOIMinistryRequest.getopenrequestsbyapplicantid(applicantschema['foiRequestApplicantID']) for request in requests: diff --git a/request-management-api/request_api/services/foirequest/requestservicecreate.py b/request-management-api/request_api/services/foirequest/requestservicecreate.py index 144a58a62..4563aa746 100644 --- a/request-management-api/request_api/services/foirequest/requestservicecreate.py +++ b/request-management-api/request_api/services/foirequest/requestservicecreate.py @@ -129,13 +129,11 @@ def __prepareapplicants(self, foirequestschema, userid): selfalsoknownas=None selfdob=None selfcategoryid=None - print("foirequestschema", foirequestschema) if foirequestschema.get("additionalPersonalInfo") is not None and foirequestschema.get('requeststatusid') == 1: applicantinfo = foirequestschema.get("additionalPersonalInfo") selfdob = applicantinfo["birthDate"] if requestservicebuilder().isNotBlankorNone(foirequestschema,"birthDate","additionalPersonalInfo") else None selfalsoknownas = applicantinfo["alsoKnownAs"] if requestservicebuilder().isNotBlankorNone(foirequestschema,"alsoKnownAs","additionalPersonalInfo") else None selfcategoryid = requestserviceconfigurator().getvalueof("category",foirequestschema.get("category")) if requestservicebuilder().isNotBlankorNone(foirequestschema,"category","main") else None - print("selfcategoryid", selfcategoryid) # if foirequestschema.get('foiRequestApplicantID') is None and foirequestschema.get('requeststatusid') == 1: if foirequestschema.get('foiRequestApplicantID') is not None: From e3902cfb2ddcea3978267d5c723f8bbadbafc80f Mon Sep 17 00:00:00 2001 From: Richard Qi Date: Fri, 19 Jan 2024 17:11:56 -0800 Subject: [PATCH 222/238] bug fix --- .../request_api/models/FOIRequestApplicants.py | 3 ++- request-management-api/request_api/schemas/foiapplicant.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/request-management-api/request_api/models/FOIRequestApplicants.py b/request-management-api/request_api/models/FOIRequestApplicants.py index f2c715717..c70e5e406 100644 --- a/request-management-api/request_api/models/FOIRequestApplicants.py +++ b/request-management-api/request_api/models/FOIRequestApplicants.py @@ -68,6 +68,7 @@ def updateapplicantprofile(cls, foirequestapplicantid, firstname, lastname, midd # applicant.isactive = False applicant_query.update({FOIRequestApplicant.applicantprofileid:str(uuid.uuid4())}) + dob = datetime.strptime(dob, "%Y-%m-%d") if dob is not None and dob != '' else None applicantfromform = FOIRequestApplicant().prepareapplicantforcomparing(firstname, lastname, middlename, businessname, alsoknownas, dob, applicantcategoryid) applicantfromdb = FOIRequestApplicant().prepareapplicantforcomparing(applicant.firstname, applicant.lastname, applicant.middlename, applicant.businessname, applicant.alsoknownas, applicant.dob, applicant.applicantcategoryid) if applicantfromform != applicantfromdb: @@ -1221,7 +1222,7 @@ def prepareapplicantforcomparing(cls, firstname, lastname, middlename, businessn 'middlename': middlename if middlename is not None or middlename != '' else None, 'businessname': businessname if businessname is not None or businessname != '' else None, 'alsoknownas': alsoknownas if alsoknownas is not None or alsoknownas != '' else None, - 'dob': datetime.strptime(dob, "%Y-%m-%d") if dob is not None and dob != '' else None, + 'dob': dob if dob is not None and dob != '' else None, 'applicantcategoryid': applicantcategoryid if applicantcategoryid is not None or applicantcategoryid != 0 else None, } diff --git a/request-management-api/request_api/schemas/foiapplicant.py b/request-management-api/request_api/schemas/foiapplicant.py index a54c62dd1..e802f1748 100644 --- a/request-management-api/request_api/schemas/foiapplicant.py +++ b/request-management-api/request_api/schemas/foiapplicant.py @@ -31,4 +31,4 @@ class Meta: # pylint: disable=too-few-public-methods foiRequestApplicantID = fields.Int(data_key="foiRequestApplicantID",required=False,allow_none=True) foirequestID = fields.List(fields.Int(),data_key="foirequestID",required=False,allow_none=False) additionalPersonalInfo = fields.Nested(FOIAdditionallPersonalInfoWrapperSchema,required=False,allow_none=True) - category = fields.Int(data_key="category",required=False,allow_none=True) \ No newline at end of file + category = fields.Str(data_key="category",allow_none=True) \ No newline at end of file From cfb25e2bb5b65b3206492e0f273260e96c2a4101 Mon Sep 17 00:00:00 2001 From: Richard Qi Date: Tue, 23 Jan 2024 00:58:08 -0800 Subject: [PATCH 223/238] bug fix --- .../request_api/models/FOIMinistryRequests.py | 8 ++-- .../models/FOIRequestApplicantMappings.py | 45 ++++++++++++++++++- .../foirequest/requestservicecreate.py | 7 ++- .../foirequest/requestservicegetter.py | 40 ++++++++--------- .../requestserviceministrybuilder.py | 4 +- 5 files changed, 72 insertions(+), 32 deletions(-) diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index 3233f4716..dac8bc5cd 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -176,10 +176,10 @@ def getrequests(cls, group = None): ministryrequest =ministryrequest_schema.dump(_session.query(FOIMinistryRequest).filter(FOIMinistryRequest.foiministryrequestid == _requestid).order_by(FOIMinistryRequest.version.desc()).first()) parentrequest = _session.query(FOIRequest).filter(FOIRequest.foirequestid == ministryrequest['foirequest_id'] and FOIRequest.version == ministryrequest['foirequestversion_id']).order_by(FOIRequest.version.desc()).first() - requestapplicants = FOIRequestApplicantMapping.getrequestapplicants(ministryrequest['foirequest_id'],ministryrequest['foirequestversion_id']) + requestapplicants = FOIRequestApplicantMapping.getrequestapplicantinfos(ministryrequest['foirequest_id'],ministryrequest['foirequestversion_id']) _receiveddate = parentrequest.receiveddate - _request["firstName"] = requestapplicants[0]['foirequestapplicant.firstname'] - _request["lastName"] = requestapplicants[0]['foirequestapplicant.lastname'] + _request["firstName"] = requestapplicants[0]['firstname'] + _request["lastName"] = requestapplicants[0]['lastname'] _request["requestType"] = parentrequest.requesttype _request["idNumber"] = ministryrequest['filenumber'] _request["axisRequestId"] = ministryrequest['axisrequestid'] @@ -199,7 +199,7 @@ def getrequests(cls, group = None): _request["id"] = parentrequest.foirequestid _request["ministryrequestid"] = ministryrequest['foiministryrequestid'] # _request["applicantcategory"]=parentrequest.applicantcategory.name - _request["applicantcategory"]=requestapplicants[0]['foirequestapplicant.applicantcategory.name'] + _request["applicantcategory"]=requestapplicants[0]['applicantcategory'] _request["identityverified"] = ministryrequest['identityverified'] _requests.append(_request) diff --git a/request-management-api/request_api/models/FOIRequestApplicantMappings.py b/request-management-api/request_api/models/FOIRequestApplicantMappings.py index 7313e1f1a..412a1d8a5 100644 --- a/request-management-api/request_api/models/FOIRequestApplicantMappings.py +++ b/request-management-api/request_api/models/FOIRequestApplicantMappings.py @@ -5,7 +5,9 @@ from sqlalchemy.orm import relationship,backref from .default_method_result import DefaultMethodResult from .FOIRequests import FOIRequest -from sqlalchemy import and_, or_ +from sqlalchemy import and_, or_, func +from .ApplicantCategories import ApplicantCategory +from .RequestorType import RequestorType class FOIRequestApplicantMapping(db.Model): # Name of the table in our database @@ -46,8 +48,47 @@ def getrequestapplicants(cls,foirequest_id,foirequestversion): ).order_by(FOIRequestApplicantMapping.foirequestapplicantmappingid.asc()).all() applicantinfos = requestapplicant_schema.dump(_applicantinfos) return applicantinfos - + + @classmethod + def getrequestapplicantinfos(cls,foirequest_id,foirequestversion): + from .FOIRequestApplicants import FOIRequestApplicant + _applicantinfos = db.session.query(*[ + FOIRequestApplicantMapping.foirequestapplicantmappingid, + FOIRequestApplicantMapping.foirequest_id.label('foirequestid'), + FOIRequestApplicantMapping.foirequestversion_id.label('version'), + FOIRequestApplicantMapping.requestortypeid.label('requestortypeid'), + RequestorType.name.label('requestortype'), + FOIRequestApplicant.foirequestapplicantid.label('foirequestapplicantid'), + FOIRequestApplicant.firstname.label('firstname'), + FOIRequestApplicant.lastname.label('lastname'), + FOIRequestApplicant.middlename.label('middlename'), + FOIRequestApplicant.alsoknownas.label('alsoknownas'), + FOIRequestApplicant.dob.label('dob'), + FOIRequestApplicant.businessname.label('businessname'), + ApplicantCategory.applicantcategoryid.label('applicantcategoryid'), + ApplicantCategory.name.label('applicantcategory'), + ]).join( + FOIRequestApplicant, + FOIRequestApplicant.foirequestapplicantid == FOIRequestApplicantMapping.foirequestapplicantid + ).join( + ApplicantCategory, + ApplicantCategory.applicantcategoryid == FOIRequestApplicant.applicantcategoryid + ).join( + RequestorType, + RequestorType.requestortypeid == FOIRequestApplicantMapping.requestortypeid + ).filter( + FOIRequestApplicantMapping.foirequest_id == foirequest_id, + FOIRequestApplicantMapping.foirequestversion_id == foirequestversion + ).order_by(FOIRequestApplicantMapping.foirequestapplicantmappingid.asc()).all() + requestapplicant_schema = FOIRequestApplicantInfoSchema(many=True) + applicantinfos = requestapplicant_schema.dump(_applicantinfos) + return applicantinfos + class FOIRequestApplicantMappingSchema(ma.Schema): class Meta: fields = ('foirequestapplicantmappingid','foirequest.foirequestid','foirequest.version','requestortype.requestortypeid','requestortype.name','foirequestapplicant.foirequestapplicantid','foirequestapplicant.firstname','foirequestapplicant.lastname','foirequestapplicant.middlename','foirequestapplicant.alsoknownas','foirequestapplicant.dob','foirequestapplicant.businessname','foirequestapplicant.applicantcategory.applicantcategoryid','foirequestapplicant.applicantcategory.name') + +class FOIRequestApplicantInfoSchema(ma.Schema): + class Meta: + fields = ('foirequestapplicantmappingid','foirequestid','version','requestortypeid','requestortype','foirequestapplicantid','firstname','lastname','middlename','alsoknownas','dob','businessname','applicantcategoryid','applicantcategory') \ No newline at end of file diff --git a/request-management-api/request_api/services/foirequest/requestservicecreate.py b/request-management-api/request_api/services/foirequest/requestservicecreate.py index 4563aa746..e3a046e66 100644 --- a/request-management-api/request_api/services/foirequest/requestservicecreate.py +++ b/request-management-api/request_api/services/foirequest/requestservicecreate.py @@ -70,7 +70,7 @@ def saverequestversion(self,foirequestschema, foirequestid , ministryid, userid) def saveministryrequestversion(self,ministryrequestschema, foirequestid , ministryid, userid, usertype = None): _foirequest = FOIRequest().getrequest(foirequestid) _foiministryrequest = FOIMinistryRequest().getrequestbyministryrequestid(ministryid) - _foirequestapplicant = FOIRequestApplicantMapping().getrequestapplicants(foirequestid,_foirequest["version"]) + _foirequestapplicant = FOIRequestApplicantMapping().getrequestapplicantinfos(foirequestid,_foirequest["version"]) _foirequestcontact = FOIRequestContactInformation().getrequestcontactinformation(foirequestid,_foirequest["version"]) _foirequestpersonalattrbs = FOIRequestPersonalAttribute().getrequestpersonalattributes(foirequestid,_foirequest["version"]) foiministryrequestarr = [] @@ -128,12 +128,11 @@ def __prepareapplicants(self, foirequestschema, userid): requestapplicantarr = [] selfalsoknownas=None selfdob=None - selfcategoryid=None - if foirequestschema.get("additionalPersonalInfo") is not None and foirequestschema.get('requeststatusid') == 1: + selfcategoryid = requestserviceconfigurator().getvalueof("category",foirequestschema.get("category")) if requestservicebuilder().isNotBlankorNone(foirequestschema,"category","main") == True else None + if foirequestschema.get("additionalPersonalInfo") is not None: applicantinfo = foirequestschema.get("additionalPersonalInfo") selfdob = applicantinfo["birthDate"] if requestservicebuilder().isNotBlankorNone(foirequestschema,"birthDate","additionalPersonalInfo") else None selfalsoknownas = applicantinfo["alsoKnownAs"] if requestservicebuilder().isNotBlankorNone(foirequestschema,"alsoKnownAs","additionalPersonalInfo") else None - selfcategoryid = requestserviceconfigurator().getvalueof("category",foirequestschema.get("category")) if requestservicebuilder().isNotBlankorNone(foirequestschema,"category","main") else None # if foirequestschema.get('foiRequestApplicantID') is None and foirequestschema.get('requeststatusid') == 1: if foirequestschema.get('foiRequestApplicantID') is not None: diff --git a/request-management-api/request_api/services/foirequest/requestservicegetter.py b/request-management-api/request_api/services/foirequest/requestservicegetter.py index ee3add1a0..538dc1487 100644 --- a/request-management-api/request_api/services/foirequest/requestservicegetter.py +++ b/request-management-api/request_api/services/foirequest/requestservicegetter.py @@ -24,7 +24,7 @@ def getrequest(self,foirequestid,foiministryrequestid): request = FOIRequest.getrequest(foirequestid) requestministry = FOIMinistryRequest.getrequestbyministryrequestid(foiministryrequestid) requestcontactinformation = FOIRequestContactInformation.getrequestcontactinformation(foirequestid,request['version']) - requestapplicants = FOIRequestApplicantMapping.getrequestapplicants(foirequestid,request['version']) + requestapplicants = FOIRequestApplicantMapping.getrequestapplicantinfos(foirequestid,request['version']) requestministrydivisions = FOIMinistryRequestDivision.getdivisions(foiministryrequestid,requestministry['version']) iaorestrictrequestdetails = FOIRestrictedMinistryRequest.getrestricteddetails(ministryrequestid=foiministryrequestid,type='iao') @@ -38,17 +38,17 @@ def getrequest(self,foirequestid,foiministryrequestid): additionalpersonalinfo ={} for applicant in requestapplicants: - firstname = applicant['foirequestapplicant.firstname'] - middlename = applicant['foirequestapplicant.middlename'] - lastname = applicant['foirequestapplicant.lastname'] - businessname = applicant['foirequestapplicant.businessname'] - dobraw = applicant['foirequestapplicant.dob'] + firstname = applicant['firstname'] + middlename = applicant['middlename'] + lastname = applicant['lastname'] + businessname = applicant['businessname'] + dobraw = applicant['dob'] dob = parse(dobraw).strftime(self.__genericdateformat()) if dobraw is not None else '' - alsoknownas = applicant['foirequestapplicant.alsoknownas'] - foirequestapplicantid = applicant['foirequestapplicant.foirequestapplicantid'] - requestortypeid = applicant['requestortype.requestortypeid'] - categoryid = applicant['foirequestapplicant.applicantcategory.applicantcategoryid'] - category = applicant['foirequestapplicant.applicantcategory.name'] + alsoknownas = applicant['alsoknownas'] + foirequestapplicantid = applicant['foirequestapplicantid'] + requestortypeid = applicant['requestortypeid'] + categoryid = applicant['applicantcategoryid'] + category = applicant['applicantcategory'] if requestortypeid == 1: baserequestinfo.update(self.__prepareapplicant(foirequestapplicantid, firstname, middlename, lastname, businessname, categoryid, category)) @@ -87,18 +87,18 @@ def getrequestdetailsforministry(self,foirequestid,foiministryrequestid, authmem baserequestinfo = self.__preparebaseinfo(request,foiministryrequestid,requestministry,requestministrydivisions) if request['requesttype'] == 'personal': - requestapplicants = FOIRequestApplicantMapping.getrequestapplicants(foirequestid,request['version']) + requestapplicants = FOIRequestApplicantMapping.getrequestapplicantinfos(foirequestid,request['version']) additionalpersonalinfo ={} for applicant in requestapplicants: - firstname = applicant['foirequestapplicant.firstname'] - middlename = applicant['foirequestapplicant.middlename'] - lastname = applicant['foirequestapplicant.lastname'] - dobraw = applicant['foirequestapplicant.dob'] + firstname = applicant['firstname'] + middlename = applicant['middlename'] + lastname = applicant['lastname'] + dobraw = applicant['dob'] dob = parse(dobraw).strftime(self.__genericdateformat()) if dobraw is not None else '' - foirequestapplicantid = applicant['foirequestapplicant.foirequestapplicantid'] - requestortypeid = applicant['requestortype.requestortypeid'] - categoryid = applicant['foirequestapplicant.applicantcategory.applicantcategoryid'] - category = applicant['foirequestapplicant.applicantcategory.name'] + foirequestapplicantid = applicant['foirequestapplicantid'] + requestortypeid = applicant['requestortypeid'] + categoryid = applicant['applicantcategoryid'] + category = applicant['applicantcategory'] businessname = None if requestortypeid == 1: diff --git a/request-management-api/request_api/services/foirequest/requestserviceministrybuilder.py b/request-management-api/request_api/services/foirequest/requestserviceministrybuilder.py index 7928588b7..d0943bb84 100644 --- a/request-management-api/request_api/services/foirequest/requestserviceministrybuilder.py +++ b/request-management-api/request_api/services/foirequest/requestserviceministrybuilder.py @@ -148,8 +148,8 @@ def createfoirequestappplicantfromobject(self, requestapplicants, requestid, ver applicantmapping = FOIRequestApplicantMapping() applicantmapping.foirequest_id = requestid applicantmapping.foirequestversion_id = version - applicantmapping.foirequestapplicantid = requestapplicant["foirequestapplicant.foirequestapplicantid"] - applicantmapping.requestortypeid = requestapplicant["requestortype.requestortypeid"] + applicantmapping.foirequestapplicantid = requestapplicant["foirequestapplicantid"] + applicantmapping.requestortypeid = requestapplicant["requestortypeid"] applicantmapping.createdby = userid requestapplicantarr.append(applicantmapping) return requestapplicantarr From 2e22b664f9bea5ec6ab5fb51c67bd9e7042e3c45 Mon Sep 17 00:00:00 2001 From: Richard Qi Date: Tue, 23 Jan 2024 12:36:38 -0800 Subject: [PATCH 224/238] bug fix --- .../models/FOIRequestApplicants.py | 26 +++++++++++++++---- .../request_api/services/applicantservice.py | 3 +-- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/request-management-api/request_api/models/FOIRequestApplicants.py b/request-management-api/request_api/models/FOIRequestApplicants.py index c70e5e406..dc1c2076e 100644 --- a/request-management-api/request_api/models/FOIRequestApplicants.py +++ b/request-management-api/request_api/models/FOIRequestApplicants.py @@ -10,7 +10,7 @@ from .FOIRequestContactInformation import FOIRequestContactInformation from .FOIRequestPersonalAttributes import FOIRequestPersonalAttribute from .FOIRequestStatus import FOIRequestStatus -from sqlalchemy import and_, or_, func, case +from sqlalchemy import and_, or_, func, text import uuid class FOIRequestApplicant(db.Model): @@ -56,17 +56,33 @@ def createapplicant(cls, firstname, lastname, middlename, businessname, alsoknow @classmethod def updateapplicantprofile(cls, foirequestapplicantid, firstname, lastname, middlename, businessname, alsoknownas, dob, applicantcategoryid, userid): + + applicantprofile = aliased(FOIRequestApplicant) + applicant_query = db.session.query( FOIRequestApplicant - ).filter_by( - foirequestapplicantid = foirequestapplicantid + ).join( + applicantprofile, + or_( + and_( + applicantprofile.foirequestapplicantid == foirequestapplicantid, + applicantprofile.applicantprofileid == FOIRequestApplicant.applicantprofileid + ), + and_( + FOIRequestApplicant.foirequestapplicantid == foirequestapplicantid, + applicantprofile.applicantprofileid.is_(None) + ) + ) ) - applicant = applicant_query.first() + applicant = applicant_query.order_by(FOIRequestApplicant.foirequestapplicantid.desc()).first() # create an applicant profile id if it's not set if(applicant.applicantprofileid is None): # applicant.isactive = False - applicant_query.update({FOIRequestApplicant.applicantprofileid:str(uuid.uuid4())}) + sql = """update "FOIRequestApplicants" set applicantprofileid = :profileid, updatedby = :userid, updated_at = now() + where foirequestapplicantid = :foirequestapplicantid""" + db.session.execute(text(sql), {'profileid': str(uuid.uuid4()), 'userid':userid, 'foirequestapplicantid': foirequestapplicantid}) + db.session.commit() dob = datetime.strptime(dob, "%Y-%m-%d") if dob is not None and dob != '' else None applicantfromform = FOIRequestApplicant().prepareapplicantforcomparing(firstname, lastname, middlename, businessname, alsoknownas, dob, applicantcategoryid) diff --git a/request-management-api/request_api/services/applicantservice.py b/request-management-api/request_api/services/applicantservice.py index dae384165..a5d20f243 100644 --- a/request-management-api/request_api/services/applicantservice.py +++ b/request-management-api/request_api/services/applicantservice.py @@ -55,9 +55,8 @@ def saveapplicantinfo(self, applicantschema, userid): userid ) # replace with applicant id once new save function is written # requests = FOIMinistryRequest.getopenrequestsbyrequestId(applicantschema['foirequestID']) - requests = FOIMinistryRequest.getopenrequestsbyapplicantid(applicantschema['foiRequestApplicantID']) applicantschema['foiRequestApplicantID'] = applicant.identifier - # requests = FOIMinistryRequest.getopenrequestsbyapplicantid(applicantschema['foiRequestApplicantID']) + requests = FOIMinistryRequest.getopenrequestsbyapplicantid(applicantschema['foiRequestApplicantID']) for request in requests: requestschema = requestservicegetter().getrequest(request['foirequest_id'], request['foiministryrequestid']) requestschema.update(applicantschema) From 1bcf64a7533d0da6bbf2af3cd42fb2399e9a61f8 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 23 Jan 2024 13:41:56 -0800 Subject: [PATCH 225/238] add yellow warning color for fields in profile that are different from request fix user trapped with no possible action bug for create new profile --- .../FOIRequest/AdditionalApplicantDetails.js | 15 ++++++++++++- .../FOI/FOIRequest/AddressContanctInfo.js | 21 +++++++++++++++++++ .../FOI/FOIRequest/ApplicantDetails.js | 16 ++++++++++++++ .../FOI/FOIRequest/ApplicantProfileModal.js | 20 ++++++++++++++---- .../foirequest/requestservicecreate.py | 2 +- 5 files changed, 68 insertions(+), 6 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/AdditionalApplicantDetails.js b/forms-flow-web/src/components/FOI/FOIRequest/AdditionalApplicantDetails.js index b5c55b678..220cb52f2 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/AdditionalApplicantDetails.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/AdditionalApplicantDetails.js @@ -10,7 +10,7 @@ import AccordionDetails from '@material-ui/core/AccordionDetails'; import Typography from '@material-ui/core/Typography'; import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; -const AdditionalApplicantDetails = React.memo(({requestDetails, createSaveRequestObject, disableInput, defaultExpanded}) => { +const AdditionalApplicantDetails = React.memo(({requestDetails, createSaveRequestObject, disableInput, defaultExpanded, warning}) => { /** * Addition Applicant details box in the UI * No mandatory fields here @@ -24,6 +24,15 @@ const AdditionalApplicantDetails = React.memo(({requestDetails, createSaveReques }, accordionSummary: { flexDirection: 'row-reverse' + }, + warning: { + '& fieldset': { + borderColor: '#ed6c02 !important' + }, + '& label': { + color: '#ed6c02 !important' + } + } }); const classes = useStyles(); @@ -140,6 +149,7 @@ const AdditionalApplicantDetails = React.memo(({requestDetails, createSaveReques inputProps={{ "aria-labelledby": "personalHealthNumber-label"}} InputLabelProps={{ shrink: true, }} variant="outlined" + className={warning && warning(FOI_COMPONENT_CONSTANTS.PERSONAL_HEALTH_NUMBER) && classes.warning} value={personalHealthNumberText} onChange={handlePersonalHealthNumber} fullWidth @@ -156,6 +166,7 @@ const AdditionalApplicantDetails = React.memo(({requestDetails, createSaveReques shrink: true, }} variant="outlined" + className={warning && warning(FOI_COMPONENT_CONSTANTS.DOB) && classes.warning} fullWidth disabled={disableInput} /> @@ -179,6 +190,7 @@ const AdditionalApplicantDetails = React.memo(({requestDetails, createSaveReques inputProps={{ "aria-labelledby": "correctionsNumber-label"}} InputLabelProps={{ shrink: true, }} variant="outlined" + className={warning && warning(FOI_COMPONENT_CONSTANTS.CORRECTIONS_NUMBER) && classes.warning} value={correctionsNumberText} onChange={handleCorrectionsNumber} fullWidth @@ -191,6 +203,7 @@ const AdditionalApplicantDetails = React.memo(({requestDetails, createSaveReques InputLabelProps={{ shrink: true, }} variant="outlined" value={employeeNumberText} + className={warning && warning(FOI_COMPONENT_CONSTANTS.EMPLOYEE_NUMBER) && classes.warning} onChange={handleEmployeeNumber} fullWidth disabled={disableInput} diff --git a/forms-flow-web/src/components/FOI/FOIRequest/AddressContanctInfo.js b/forms-flow-web/src/components/FOI/FOIRequest/AddressContanctInfo.js index 60807d59a..8752825bb 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/AddressContanctInfo.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/AddressContanctInfo.js @@ -23,6 +23,15 @@ const useStyles = makeStyles((_theme) => ({ }, accordionSummary: { flexDirection: 'row-reverse' + }, + warning: { + '& fieldset': { + borderColor: '#ed6c02 !important' + }, + '& label': { + color: '#ed6c02 !important' + } + } })); @@ -37,6 +46,7 @@ const AddressContactDetails = memo( disableInput, defaultExpanded, moreInfoAction, + warning }) => { const classes = useStyles(); /** @@ -328,6 +338,7 @@ const AddressContactDetails = memo( InputLabelProps={{ shrink: true }} value={emailText} variant="outlined" + className={warning && warning(FOI_COMPONENT_CONSTANTS.APPLICANT_EMAIL) && classes.warning} fullWidth required={true} disabled={disableInput} @@ -349,6 +360,7 @@ const AddressContactDetails = memo( label="Home Phone" InputLabelProps={{ shrink: true }} variant="outlined" + className={warning && warning(FOI_COMPONENT_CONSTANTS.HOME_PHONE) && classes.warning} value={homePhoneText} onChange={handleHomePhoneChange} fullWidth @@ -362,6 +374,7 @@ const AddressContactDetails = memo( label="Mobile Phone" InputLabelProps={{ shrink: true }} variant="outlined" + className={warning && warning(FOI_COMPONENT_CONSTANTS.MOBILE_PHONE) && classes.warning} value={mobilePhoneText} onChange={handleMobilePhoneChange} fullWidth @@ -375,6 +388,7 @@ const AddressContactDetails = memo( label="Work Phone" InputLabelProps={{ shrink: true }} variant="outlined" + className={warning && warning(FOI_COMPONENT_CONSTANTS.WORK_PHONE_PRIMARY) && classes.warning} value={workPhonePrimaryText} onChange={handleWorkPhonePrimaryChange} fullWidth @@ -388,6 +402,7 @@ const AddressContactDetails = memo( label="Alternative Phone" InputLabelProps={{ shrink: true }} variant="outlined" + className={warning && warning(FOI_COMPONENT_CONSTANTS.WORK_PHONE_SECONDARY) && classes.warning} value={workPhoneSecondaryText} onChange={handleWorkPhoneSecondarChange} fullWidth @@ -403,6 +418,7 @@ const AddressContactDetails = memo( label="Street Address" InputLabelProps={{ shrink: true }} variant="outlined" + className={warning && warning(FOI_COMPONENT_CONSTANTS.STREET_ADDRESS_PRIMARY) && classes.warning} value={streetAddressText} onChange={handleStreetAddressChange} fullWidth @@ -418,6 +434,7 @@ const AddressContactDetails = memo( label="Secondary Street Address" InputLabelProps={{ shrink: true }} variant="outlined" + className={warning && warning(FOI_COMPONENT_CONSTANTS.STREET_ADDRESS_SECONDARY) && classes.warning} value={secondaryStreetAddressText} onChange={handleScondaryStreetAddressChange} fullWidth @@ -431,6 +448,7 @@ const AddressContactDetails = memo( label="City" InputLabelProps={{ shrink: true }} variant="outlined" + className={warning && warning(FOI_COMPONENT_CONSTANTS.CITY) && classes.warning} value={CityText} onChange={handleCityChange} fullWidth @@ -446,6 +464,7 @@ const AddressContactDetails = memo( label="Province" InputLabelProps={{ shrink: true }} variant="outlined" + className={warning && warning(FOI_COMPONENT_CONSTANTS.PROVINCE) && classes.warning} value={ProvinceText} onChange={handleProvinceChange} fullWidth @@ -461,6 +480,7 @@ const AddressContactDetails = memo( label="Country" InputLabelProps={{ shrink: true }} variant="outlined" + className={warning && warning(FOI_COMPONENT_CONSTANTS.COUNTRY) && classes.warning} value={CountryText} onChange={handleCountryChange} fullWidth @@ -476,6 +496,7 @@ const AddressContactDetails = memo( label="Postal Code" InputLabelProps={{ shrink: true }} variant="outlined" + className={warning && warning(FOI_COMPONENT_CONSTANTS.POSTALCODE) && classes.warning} value={PostalText} onChange={handlePostalChange} inputProps={{ maxLength: 6 }} diff --git a/forms-flow-web/src/components/FOI/FOIRequest/ApplicantDetails.js b/forms-flow-web/src/components/FOI/FOIRequest/ApplicantDetails.js index 9c01c5efb..c51a165d7 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/ApplicantDetails.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/ApplicantDetails.js @@ -23,6 +23,7 @@ const ApplicantDetails = React.memo( requestStatus, defaultExpanded, showHistory, + warning }) => { const useStyles = makeStyles({ @@ -33,6 +34,15 @@ const ApplicantDetails = React.memo( }, accordionSummary: { flexDirection: 'row-reverse' + }, + warning: { + '& fieldset': { + borderColor: '#ed6c02 !important' + }, + '& label': { + color: '#ed6c02 !important' + } + } }); const classes = useStyles(); @@ -257,6 +267,7 @@ const ApplicantDetails = React.memo( inputProps={{ "aria-labelledby": "firstName-label"}} InputLabelProps={{ shrink: true }} variant="outlined" + className={warning && warning(FOI_COMPONENT_CONSTANTS.APPLICANT_FIRST_NAME) && classes.warning} value={applicantFirstNameText} fullWidth onChange={handleFirtNameChange} @@ -271,6 +282,7 @@ const ApplicantDetails = React.memo( InputLabelProps={{ shrink: true }} value={applicantMiddleNameText} variant="outlined" + className={warning && warning(FOI_COMPONENT_CONSTANTS.APPLICANT_MIDDLE_NAME) && classes.warning} fullWidth disabled={disableInput} onChange={handleMiddleNameChange} @@ -282,6 +294,7 @@ const ApplicantDetails = React.memo( InputLabelProps={{ shrink: true }} value={applicantLastNameText} variant="outlined" + className={warning && warning(FOI_COMPONENT_CONSTANTS.APPLICANT_LAST_NAME) && classes.warning} fullWidth onChange={handleLastNameChange} required={true} @@ -296,6 +309,7 @@ const ApplicantDetails = React.memo( inputProps={{ "aria-labelledby": "organization-label"}} InputLabelProps={{ shrink: true }} value={organizationText} + className={warning && warning(FOI_COMPONENT_CONSTANTS.ORGANIZATION) && classes.warning} variant="outlined" fullWidth disabled={disableInput} @@ -311,6 +325,7 @@ const ApplicantDetails = React.memo( onChange={handleCategoryOnChange} input={} variant="outlined" + className={warning && warning(FOI_COMPONENT_CONSTANTS.FOI_CATEGORY) && classes.warning} fullWidth required disabled={disableInput || disableFieldForMinistryRequest} @@ -325,6 +340,7 @@ const ApplicantDetails = React.memo( InputLabelProps={{ shrink: true }} value={alsoKnownAsText} variant="outlined" + className={warning && warning(FOI_COMPONENT_CONSTANTS.ALSO_KNOWN_AS) && classes.warning} fullWidth disabled={disableInput} onChange={handleAlsoKnownAsChange} diff --git a/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js b/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js index ffa373c5a..e765b0fbb 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js @@ -349,6 +349,7 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { if (!createConfirmation) { setCreateConfirmation(true); } else { + dispatch(setFOIRequestApplicantProfile({foiRequestApplicantID: -1})); handleClose(); } } @@ -361,6 +362,14 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { } } + const warning = (field) => { + if ([FOI_COMPONENT_CONSTANTS.DOB, FOI_COMPONENT_CONSTANTS.PERSONAL_HEALTH_NUMBER, FOI_COMPONENT_CONSTANTS.ALSO_KNOWN_AS].includes(field)) { + return requestDetails.additionalPersonalInfo?.[field] && requestDetails.additionalPersonalInfo[field] !== saveApplicantObject?.additionalPersonalInfo[field] + } else { + return requestDetails[field] && requestDetails[field] !== saveApplicantObject?.[field] + } + } + return (
@@ -481,6 +490,7 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { disableInput={false} defaultExpanded={true} showHistory={showApplicantHistory} + warning={warning} /> { handleEmailValidation={() => {}} disableInput={false} defaultExpanded={false} + warning={warning} /> ) : diff --git a/request-management-api/request_api/services/foirequest/requestservicecreate.py b/request-management-api/request_api/services/foirequest/requestservicecreate.py index 4563aa746..bc1926a36 100644 --- a/request-management-api/request_api/services/foirequest/requestservicecreate.py +++ b/request-management-api/request_api/services/foirequest/requestservicecreate.py @@ -136,7 +136,7 @@ def __prepareapplicants(self, foirequestschema, userid): selfcategoryid = requestserviceconfigurator().getvalueof("category",foirequestschema.get("category")) if requestservicebuilder().isNotBlankorNone(foirequestschema,"category","main") else None # if foirequestschema.get('foiRequestApplicantID') is None and foirequestschema.get('requeststatusid') == 1: - if foirequestschema.get('foiRequestApplicantID') is not None: + if foirequestschema.get('foiRequestApplicantID', 0) > 0: applicant = FOIRequestApplicant().getlatestprofilebyapplicantid(foirequestschema['foiRequestApplicantID']) requestapplicant = FOIRequestApplicantMapping() requestapplicant.foirequestapplicantid = applicant['foirequestapplicantid'] From 5f77f919edfb00df3aac7669687432b76da5d37e Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 23 Jan 2024 16:59:59 -0800 Subject: [PATCH 226/238] save changes for all intake in progress requests associated to applicants --- .../FOI/FOIRequest/ApplicantProfileModal.js | 2 +- .../request_api/models/FOIRawRequests.py | 12 +++++++++++- .../request_api/services/applicantservice.py | 16 ++++++++++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js b/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js index e765b0fbb..480697762 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js @@ -432,7 +432,7 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { {selectedApplicant ? confirmationMessage ? -
Are you sure you would like to save changes for all open requests?

Please ensure you have checked the Request History to see the request(s) that will be affected.
+
Are you sure you would like to save changes for all open and intake in progress requests associated with this profile?

Please ensure you have checked the Request History to see the request(s) that will be affected.
: (showRequestHistory ? <> diff --git a/request-management-api/request_api/models/FOIRawRequests.py b/request-management-api/request_api/models/FOIRawRequests.py index 9a0169647..05c01c2c2 100644 --- a/request-management-api/request_api/models/FOIRawRequests.py +++ b/request-management-api/request_api/models/FOIRawRequests.py @@ -328,6 +328,16 @@ def get_request(cls,requestid): request = db.session.query(FOIRawRequest).filter_by(requestid=requestid).order_by(FOIRawRequest.version.desc()).first() return request_schema.dump(request) + @classmethod + def getrawrequestsbyapplicantid(cls,applicantid): + request_schema = FOIRawRequestSchema(many=True) + query = db.session.query(FOIRawRequest).distinct(FOIRawRequest.requestid).join( + FOIAssignee, FOIAssignee.username == FOIRawRequest.assignedto + ).filter( + FOIRawRequest.requestrawdata['foiRequestApplicantID'].astext.cast(db.Integer)==applicantid + ).order_by(FOIRawRequest.requestid, FOIRawRequest.version.desc()).all() + return request_schema.dump(query) + @classmethod def getLastStatusUpdateDate(cls,requestid,status): lastupdatedate = None @@ -1022,4 +1032,4 @@ def getlatestsection5pendings(cls): class FOIRawRequestSchema(ma.Schema): class Meta: - fields = ('requestid', 'requestrawdata', 'status','notes','created_at','wfinstanceid','version','updated_at','assignedgroup','assignedto','updatedby','createdby','sourceofsubmission','ispiiredacted','assignee.firstname','assignee.lastname', 'axisrequestid', 'axissyncdate', 'linkedrequests', 'closedate','isiaorestricted') \ No newline at end of file + fields = ('requestid', 'requestrawdata', 'status','notes','created_at','wfinstanceid','version','updated_at','assignedgroup','assignedto','updatedby','createdby','sourceofsubmission','ispiiredacted','assignee.firstname','assignee.middlename', 'assignee.lastname', 'axisrequestid', 'axissyncdate', 'linkedrequests', 'closedate','isiaorestricted') \ No newline at end of file diff --git a/request-management-api/request_api/services/applicantservice.py b/request-management-api/request_api/services/applicantservice.py index dae384165..8633cd495 100644 --- a/request-management-api/request_api/services/applicantservice.py +++ b/request-management-api/request_api/services/applicantservice.py @@ -3,8 +3,10 @@ from re import VERBOSE from request_api.models.FOIRequestApplicants import FOIRequestApplicant from request_api.models.FOIMinistryRequests import FOIMinistryRequest +from request_api.models.FOIRawRequests import FOIRawRequest from request_api.models.ApplicantCategories import ApplicantCategory from request_api.services.requestservice import requestservicegetter, requestservicecreate +from request_api.services.rawrequestservice import rawrequestservice from request_api.auth import AuthHelper from dateutil import tz, parser from flask import jsonify @@ -66,6 +68,20 @@ def saveapplicantinfo(self, applicantschema, userid): ) if not responseschema.success: return responseschema + rawrequests = FOIRawRequest.getrawrequestsbyapplicantid(applicantschema['foiRequestApplicantID']) + for rawrequest in rawrequests: + rawrequest['requestrawdata'].update(applicantschema) + rawrequestservice().saverawrequestversion( + rawrequest['requestrawdata'], + rawrequest['requestid'], + rawrequest['assignedgroup'], + rawrequest['assignedto'], + rawrequest['status'], + userid, + rawrequest['assignee.firstname'], + rawrequest['assignee.middlename'], + rawrequest['assignee.lastname'] + ) return DefaultMethodResult(True,'Applicant Info Updated',applicantschema['foiRequestApplicantID']) def __validateandtransform(self, filterfields): From 5806919a55e6700795f06003b2183189c6a70ed7 Mon Sep 17 00:00:00 2001 From: "sumathi.thirumani" Date: Wed, 24 Jan 2024 11:41:52 -0800 Subject: [PATCH 227/238] Changes to resolve payment issue + Merge (rootcause) --- .../request_api/services/requestservice.py | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/request-management-api/request_api/services/requestservice.py b/request-management-api/request_api/services/requestservice.py index 547ac5bbf..2bc99921a 100644 --- a/request-management-api/request_api/services/requestservice.py +++ b/request-management-api/request_api/services/requestservice.py @@ -252,6 +252,8 @@ def postcorrespondenceeventtoworkflow( attributes, ) + + def calculateduedate(self, ministryrequestid, foirequest, paymentdate): duedate_includeoffhold, cfrduedate_includeoffhold = self.__isincludeoffhold() onhold_extend_days = duecalculator().getbusinessdaysbetween(foirequest["onholdTransitionDate"], paymentdate) @@ -262,21 +264,36 @@ def calculateduedate(self, ministryrequestid, foirequest, paymentdate): calc_cfrduedate = duecalculator().addbusinessdays(foirequest["cfrDueDate"], cfrduedate_extend_days) return calc_duedate, calc_cfrduedate - def __skipduedatecalculation(self, ministryrequestid, offholddate): + + + + def __skipduedatecalculation(self, ministryrequestid, offholddate, currentstatus="", nextstatename=""): previousoffholddate = FOIMinistryRequest.getlastoffholddate(ministryrequestid) + if ( + currentstatus not in (None, "") + and currentstatus == StateName.onhold.value + and nextstatename not in (None, "") + and currentstatus == nextstatename + ): + return True + if previousoffholddate not in (None, ""): + previouspaymentdate_pst = datetimehandler().convert_to_pst( + previousoffholddate + ) + if ( + datetimehandler().getdate(previouspaymentdate_pst).date() + == datetimehandler().getdate(offholddate).date() + ): + return True foiministry_request = FOIMinistryRequest.getrequest(ministryrequestid) request_reopened = self.__hasreopened(ministryrequestid, "ministryrequest") - if previousoffholddate not in (None, ''): - previouspaymentdate_pst = datetimehandler().convert_to_pst(previousoffholddate) - if datetimehandler().getdate(previouspaymentdate_pst).date() == datetimehandler().getdate(offholddate).date(): - return True if foiministry_request['isoipcreview'] == True and request_reopened: return True return False def __isincludeoffhold(self): - payment_config_str = os.getenv("PAYMENT_CONFIG",'') - if payment_config_str in (None, ''): + payment_config_str = os.getenv("PAYMENT_CONFIG","") + if payment_config_str in (None, ""): return True, True _paymentconfig = json.loads(payment_config_str) duedate_includeoffhold = True if _paymentconfig["duedate"]["includeoffhold"] == "Y" else False From 4ec1da3a5c45ca3719318a7174a81afcd14294ec Mon Sep 17 00:00:00 2001 From: "sumathi.thirumani" Date: Wed, 24 Jan 2024 13:44:53 -0800 Subject: [PATCH 228/238] Remove json DT error from logging + (Postpone leverage the right encoder) --- .../request_api/services/email/senderservice.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/request-management-api/request_api/services/email/senderservice.py b/request-management-api/request_api/services/email/senderservice.py index d15069ca7..8a0b62ba2 100644 --- a/request-management-api/request_api/services/email/senderservice.py +++ b/request-management-api/request_api/services/email/senderservice.py @@ -31,7 +31,7 @@ class senderservice: """ def send(self, servicekey, content, _messageattachmentlist, requestjson): - logging.debug("Begin: Send email for request = "+json.dumps(requestjson)) + #logging.debug("Begin: Send email for request = "+json.dumps(requestjson)) msg = MIMEMultipart() msg['From'] = MAIL_FROM_ADDRESS msg['To'] = requestjson["email"] @@ -56,7 +56,7 @@ def send(self, servicekey, content, _messageattachmentlist, requestjson): #smtpobj.login(MAIL_SRV_USERID, MAIL_SRV_PASSWORD) smtpobj.sendmail(msg['From'], msg['To'], msg.as_string()) smtpobj.quit() - logging.debug("End: Send email for request = "+json.dumps(requestjson)) + #logging.debug("End: Send email for request = "+json.dumps(requestjson)) return {"success" : True, "message": "Sent successfully"} except Exception as e: logging.exception(e) From 17339f014da531b44aa5abc19ca4cb5a625d1d03 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 24 Jan 2024 14:50:24 -0800 Subject: [PATCH 229/238] get raw requests as part of applicant request history separate update for additional personal info as it was being overwritten due to being nested search for all previous applicant ids when updating raw requests update any previous applicant ids in raw request when saving applicant info --- .../request_api/models/FOIRawRequests.py | 6 +++++- .../request_api/services/applicantservice.py | 17 +++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/request-management-api/request_api/models/FOIRawRequests.py b/request-management-api/request_api/models/FOIRawRequests.py index 05c01c2c2..63ff03841 100644 --- a/request-management-api/request_api/models/FOIRawRequests.py +++ b/request-management-api/request_api/models/FOIRawRequests.py @@ -14,6 +14,7 @@ from .FOIMinistryRequests import FOIMinistryRequest from .FOIRawRequestWatchers import FOIRawRequestWatcher +from .FOIRequestApplicants import FOIRequestApplicant from .FOIAssignees import FOIAssignee import logging from dateutil import parser @@ -331,10 +332,13 @@ def get_request(cls,requestid): @classmethod def getrawrequestsbyapplicantid(cls,applicantid): request_schema = FOIRawRequestSchema(many=True) + applicant_subquery = db.session.query(FOIRequestApplicant.applicantprofileid).filter(FOIRequestApplicant.foirequestapplicantid == applicantid).subquery() + subquery_applicant_id_list = db.session.query(FOIRequestApplicant.foirequestapplicantid).filter(applicant_subquery.c.applicantprofileid == FOIRequestApplicant.applicantprofileid).subquery() query = db.session.query(FOIRawRequest).distinct(FOIRawRequest.requestid).join( FOIAssignee, FOIAssignee.username == FOIRawRequest.assignedto ).filter( - FOIRawRequest.requestrawdata['foiRequestApplicantID'].astext.cast(db.Integer)==applicantid + FOIRawRequest.requestrawdata['foiRequestApplicantID'].astext.cast(db.Integer).in_(subquery_applicant_id_list), + FOIRawRequest.status.notin_(['Archived', 'Closed']) ).order_by(FOIRawRequest.requestid, FOIRawRequest.version.desc()).all() return request_schema.dump(query) diff --git a/request-management-api/request_api/services/applicantservice.py b/request-management-api/request_api/services/applicantservice.py index 8633cd495..aec22d27f 100644 --- a/request-management-api/request_api/services/applicantservice.py +++ b/request-management-api/request_api/services/applicantservice.py @@ -70,7 +70,9 @@ def saveapplicantinfo(self, applicantschema, userid): return responseschema rawrequests = FOIRawRequest.getrawrequestsbyapplicantid(applicantschema['foiRequestApplicantID']) for rawrequest in rawrequests: + additionalPersonalInfo = rawrequest['requestrawdata'].get('additionalPersonalInfo', {}).update(applicantschema.get('additionalPersonalInfo', {})) rawrequest['requestrawdata'].update(applicantschema) + rawrequest['requestrawdata']['additionalPersonalInfo'] = additionalPersonalInfo rawrequestservice().saverawrequestversion( rawrequest['requestrawdata'], rawrequest['requestid'], @@ -182,6 +184,11 @@ def getapplicantrequests(self, applicantid): for request in requests: requestqueue.append(self.__preparerequest(request)) + rawrequests = FOIRawRequest.getrawrequestsbyapplicantid(applicantid) + if rawrequests is not None: + for request in rawrequests: + requestqueue.append(self.__preparerawrequest(request)) + return requestqueue def __preparerequest(self, request): @@ -193,4 +200,14 @@ def __preparerequest(self, request): 'requeststatus': request["requeststatus"], 'receiveddate': request["receiveddate"], 'description': request["description"], + } + + def __preparerawrequest(self, request): + return { + 'foirequestapplicantid': request["requestrawdata"]['foiRequestApplicantID'], + 'axisrequestid': request["axisrequestid"], + 'filenumber': 'U-00' + str(request["requestid"]), + 'requeststatus': request["status"], + 'receiveddate': request["requestrawdata"]["receivedDate"], + 'description': request["requestrawdata"]["description"], } \ No newline at end of file From f663e5648d5004876c414caf89e639c9ea902dc3 Mon Sep 17 00:00:00 2001 From: "sumathi.thirumani" Date: Wed, 24 Jan 2024 14:55:38 -0800 Subject: [PATCH 230/238] Remove json DT error from logging + (Postpone leverage the right encoder) --- .../request_api/services/cdogs_api_service.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/request-management-api/request_api/services/cdogs_api_service.py b/request-management-api/request_api/services/cdogs_api_service.py index 4ec2ddf66..123f68ea4 100644 --- a/request-management-api/request_api/services/cdogs_api_service.py +++ b/request-management-api/request_api/services/cdogs_api_service.py @@ -33,6 +33,7 @@ def __init__(self): def generate_receipt(self, template_hash_code: str, data): + print(data) request_body = { "options": { "cachereport": False, @@ -42,7 +43,7 @@ def generate_receipt(self, template_hash_code: str, data): }, "data": data } - json_request_body = json.dumps(request_body) + json_request_body = json.dumps(request_body, default = str) headers = { 'Content-Type': 'application/json', From 2f1a40e0d0edefeb99091047ee6d643a1c65f394 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 24 Jan 2024 15:25:11 -0800 Subject: [PATCH 231/238] disable open state only instead of entire dropdown if user has not selected profile --- .../components/FOI/FOIRequest/AddressContanctInfo.js | 7 +++---- .../FOI/FOIRequest/ApplicantProfileModal.js | 7 ++++--- .../src/components/FOI/FOIRequest/FOIRequest.js | 1 - forms-flow-web/src/components/FOI/FOIRequest/utils.js | 4 ++++ .../components/FOI/customComponents/StateDropDown.js | 11 ++++++++--- 5 files changed, 19 insertions(+), 11 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/AddressContanctInfo.js b/forms-flow-web/src/components/FOI/FOIRequest/AddressContanctInfo.js index 8752825bb..331554b1f 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/AddressContanctInfo.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/AddressContanctInfo.js @@ -9,8 +9,7 @@ import AccordionSummary from '@material-ui/core/AccordionSummary'; import AccordionDetails from '@material-ui/core/AccordionDetails'; import Typography from '@material-ui/core/Typography'; import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; -import ApplicantProfileModal from "./ApplicantProfileModal"; -import { StateEnum } from "../../../constants/FOI/statusEnum"; +import { isBeforeOpen } from "./utils"; const useStyles = makeStyles((_theme) => ({ row: { @@ -320,9 +319,9 @@ const AddressContactDetails = memo( type="button" className={`btn btn-link btn-description-history`} onClick={moreInfoAction} - style={(requestDetails.currentState === StateEnum.intakeinprogress.name && !requestDetails.foiRequestApplicantID) ? {color: "#9E2929"} : {}} + style={(isBeforeOpen(requestDetails) && !requestDetails.foiRequestApplicantID) ? {color: "#9E2929"} : {}} > - {(!requestDetails.stateTransition?.filter(s => s.status === StateEnum.open.name).length > 0) && 'Search' } Applicant Profiles + {(isBeforeOpen(requestDetails)) && 'Search' } Applicant Profiles } {/* ({ root: { @@ -132,7 +133,7 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { useEffect(() => { if (modalOpen) { setIsLoading(true); - if (!requestDetails.stateTransition?.filter(s => s.status === StateEnum.open.name).length > 0) { + if (isBeforeOpen(requestDetails)) { dispatch(fetchPotentialApplicants( requestDetails.firstName, requestDetails.lastName, @@ -328,7 +329,7 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { const back = () => { if (applicantHistory) { setApplicantHistory(false); - } else if (requestDetails.stateTransition?.filter(s => s.status === StateEnum.open.name).length > 0) { + } else if (!isBeforeOpen(requestDetails)) { handleClose(); } else { setSelectedApplicant(false); @@ -355,7 +356,7 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { } const isSaveDisabled = () => { - if (!requestDetails.stateTransition?.filter(s => s.status === StateEnum.open.name).length > 0) { + if (isBeforeOpen(requestDetails)) { return isProfileDifferent } else { return _.isEqual(selectedApplicant, saveApplicantObject) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index f61135e2e..ccd1df7aa 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -936,7 +936,6 @@ const FOIRequest = React.memo(({ userDetail, openApplicantProfileModal }) => { isMinistryCoordinator={false} isValidationError={isValidationError} requestType={requestDetails?.requestType} - disabled={requestDetails.currentState === StateEnum.intakeinprogress.name && !requestDetails.foiRequestApplicantID} />
diff --git a/forms-flow-web/src/components/FOI/FOIRequest/utils.js b/forms-flow-web/src/components/FOI/FOIRequest/utils.js index f4aa33500..ddf6bf5d9 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/utils.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/utils.js @@ -58,6 +58,10 @@ const getcfrDaysRemainingText = (_cfrDaysRemaining) => { return`CFR Due in ${_cfrDaysRemaining} Days` }; +export const isBeforeOpen = (requestDetails) => { + return !requestDetails.stateTransition?.filter(s => s.status === StateEnum.open.name).length > 0; +}; + export const getExtensionsCountText = (extensions) => { if (!extensions || extensions.length < 1) { return `Extensions 0`; diff --git a/forms-flow-web/src/components/FOI/customComponents/StateDropDown.js b/forms-flow-web/src/components/FOI/customComponents/StateDropDown.js index bb6fcdbb0..333a8d824 100644 --- a/forms-flow-web/src/components/FOI/customComponents/StateDropDown.js +++ b/forms-flow-web/src/components/FOI/customComponents/StateDropDown.js @@ -11,6 +11,7 @@ import { import { useSelector } from "react-redux"; import FOI_COMPONENT_CONSTANTS from "../../../constants/FOI/foiComponentConstants"; +import { isBeforeOpen } from "../FOIRequest/utils"; const StateDropDown = ({ requestState = StateEnum.unopened.name, @@ -207,12 +208,16 @@ const StateDropDown = ({ return []; } }; - const getDisableMenuItem = (index) => { + const getDisableMenuItem = (index, status) => { if (index === 0) { return false; } - return isValidationError || requestState === StateEnum.unopened.name; + return isValidationError || requestState === StateEnum.unopened.name || + (isBeforeOpen(requestDetails) + && status === 'Open' + && !requestDetails.foiRequestApplicantID + ); }; const statusList = getStatusList(); const menuItems = @@ -220,7 +225,7 @@ const StateDropDown = ({ statusList.map((item, index) => { return ( Date: Wed, 24 Jan 2024 15:57:43 -0800 Subject: [PATCH 232/238] changes to fix json datetime issue. --- .../request_api/models/FOIMinistryRequests.py | 2 +- .../request_api/services/cdogs_api_service.py | 2 +- .../request_api/services/email/senderservice.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index 40db46ec4..92ec73e7c 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -265,7 +265,7 @@ def getstatesummary(cls, ministryrequestid): _tmp_state = None for row in rs: if row["status"] != _tmp_state: - transitions.append({"status": row["status"], "version": row["version"], "created_at": row["created_at"]}) + transitions.append({"status": row["status"], "version": row["version"], "created_at": row["created_at"].strftime('%Y-%m-%d %H:%M:%S.%f')}) _tmp_state = row["status"] except Exception as ex: logging.error(ex) diff --git a/request-management-api/request_api/services/cdogs_api_service.py b/request-management-api/request_api/services/cdogs_api_service.py index 123f68ea4..767ed5cf9 100644 --- a/request-management-api/request_api/services/cdogs_api_service.py +++ b/request-management-api/request_api/services/cdogs_api_service.py @@ -43,7 +43,7 @@ def generate_receipt(self, template_hash_code: str, data): }, "data": data } - json_request_body = json.dumps(request_body, default = str) + json_request_body = json.dumps(request_body) headers = { 'Content-Type': 'application/json', diff --git a/request-management-api/request_api/services/email/senderservice.py b/request-management-api/request_api/services/email/senderservice.py index 8a0b62ba2..d15069ca7 100644 --- a/request-management-api/request_api/services/email/senderservice.py +++ b/request-management-api/request_api/services/email/senderservice.py @@ -31,7 +31,7 @@ class senderservice: """ def send(self, servicekey, content, _messageattachmentlist, requestjson): - #logging.debug("Begin: Send email for request = "+json.dumps(requestjson)) + logging.debug("Begin: Send email for request = "+json.dumps(requestjson)) msg = MIMEMultipart() msg['From'] = MAIL_FROM_ADDRESS msg['To'] = requestjson["email"] @@ -56,7 +56,7 @@ def send(self, servicekey, content, _messageattachmentlist, requestjson): #smtpobj.login(MAIL_SRV_USERID, MAIL_SRV_PASSWORD) smtpobj.sendmail(msg['From'], msg['To'], msg.as_string()) smtpobj.quit() - #logging.debug("End: Send email for request = "+json.dumps(requestjson)) + logging.debug("End: Send email for request = "+json.dumps(requestjson)) return {"success" : True, "message": "Sent successfully"} except Exception as e: logging.exception(e) From ffa30cfc8349482758c3f5a27c10fa9a9cd820f2 Mon Sep 17 00:00:00 2001 From: "sumathi.thirumani" Date: Wed, 24 Jan 2024 16:18:38 -0800 Subject: [PATCH 233/238] Remove print. --- request-management-api/request_api/services/cdogs_api_service.py | 1 - 1 file changed, 1 deletion(-) diff --git a/request-management-api/request_api/services/cdogs_api_service.py b/request-management-api/request_api/services/cdogs_api_service.py index 767ed5cf9..4ec2ddf66 100644 --- a/request-management-api/request_api/services/cdogs_api_service.py +++ b/request-management-api/request_api/services/cdogs_api_service.py @@ -33,7 +33,6 @@ def __init__(self): def generate_receipt(self, template_hash_code: str, data): - print(data) request_body = { "options": { "cachereport": False, From 2588b5f7c31a47dc2e97dec310cd4f9711ee3efe Mon Sep 17 00:00:00 2001 From: Richard Qi Date: Wed, 24 Jan 2024 17:06:38 -0800 Subject: [PATCH 234/238] migrate latest categoryid to applicant table --- .../versions/ba218164248e_add_category_to_applicant.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/request-management-api/migrations/versions/ba218164248e_add_category_to_applicant.py b/request-management-api/migrations/versions/ba218164248e_add_category_to_applicant.py index 1c474582c..73a28fdab 100644 --- a/request-management-api/migrations/versions/ba218164248e_add_category_to_applicant.py +++ b/request-management-api/migrations/versions/ba218164248e_add_category_to_applicant.py @@ -27,9 +27,13 @@ def upgrade(): set applicantcategoryid = subquery.applicantcategoryid from ( select public."FOIRequestApplicantMappings".foirequestapplicantid, public."FOIRequests".applicantcategoryid - from public."FOIRequestApplicantMappings" + from ( + select max(public."FOIRequestApplicantMappings".foirequestapplicantmappingid) as foirequestapplicantmappingid + from public."FOIRequestApplicantMappings" + group by public."FOIRequestApplicantMappings".foirequestapplicantid + ) as maxmappingid + join public."FOIRequestApplicantMappings" on public."FOIRequestApplicantMappings".foirequestapplicantmappingid = maxmappingid.foirequestapplicantmappingid join public."FOIRequests" on public."FOIRequests".foirequestid = public."FOIRequestApplicantMappings".foirequest_id and public."FOIRequests".version = public."FOIRequestApplicantMappings".foirequestversion_id - group by public."FOIRequestApplicantMappings".foirequestapplicantid, public."FOIRequests".applicantcategoryid ) as subquery where public."FOIRequestApplicants".foirequestapplicantid = subquery.foirequestapplicantid ''' From 033df00b8fbe975e0fd40f8beeea28df6e66b641 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 25 Jan 2024 15:36:57 -0800 Subject: [PATCH 235/238] minor ux improvements --- .../FOI/FOIRequest/ApplicantProfileModal.js | 29 +++++++++++-------- .../components/FOI/FOIRequest/foirequest.scss | 6 ++++ .../models/FOIRequestApplicants.py | 4 ++- .../request_api/services/applicantservice.py | 3 ++ 4 files changed, 29 insertions(+), 13 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js b/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js index 9ec25b617..7c81a3bff 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js @@ -112,6 +112,16 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { field: "filenumber", headerName: "REQUEST ID", flex: 1, + renderCell: (params) => { + return + + {params.row.filenumber} + + + } }, { field: "requeststatus", @@ -357,7 +367,7 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { const isSaveDisabled = () => { if (isBeforeOpen(requestDetails)) { - return isProfileDifferent + return false } else { return _.isEqual(selectedApplicant, saveApplicantObject) } @@ -373,7 +383,7 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { return ( -
+
{
- + {selectedApplicant ? confirmationMessage ?
Are you sure you would like to save changes for all open and intake in progress requests associated with this profile?

Please ensure you have checked the Request History to see the request(s) that will be affected.
: (showRequestHistory ? <> - + 'auto'} @@ -593,18 +604,12 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { - + Date: Fri, 26 Jan 2024 13:15:28 -0800 Subject: [PATCH 236/238] fix get profile by applicant id when profile id has not been created yet --- .../src/components/FOI/FOIRequest/ApplicantProfileModal.js | 4 ++-- .../request_api/models/FOIRequestApplicants.py | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js b/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js index 7c81a3bff..3c4359d4c 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/ApplicantProfileModal.js @@ -109,7 +109,7 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { const requestHistoryColumns = [ { - field: "filenumber", + field: "axisrequestid", headerName: "REQUEST ID", flex: 1, renderCell: (params) => { @@ -118,7 +118,7 @@ const ApplicantProfileModal = React.memo(({modalOpen, handleModalClose}) => { "/foi/foirequests/" + params.row.requestid + "/ministryrequest/" + params.row.ministryrequestid : "/foi/reviewrequest/" + params.row.requestid } target="_blank"> - {params.row.filenumber} + {params.row.axisrequestid} } diff --git a/request-management-api/request_api/models/FOIRequestApplicants.py b/request-management-api/request_api/models/FOIRequestApplicants.py index 9596a03b8..255f59a0e 100644 --- a/request-management-api/request_api/models/FOIRequestApplicants.py +++ b/request-management-api/request_api/models/FOIRequestApplicants.py @@ -107,8 +107,10 @@ def updateapplicantprofile(cls, foirequestapplicantid, firstname, lastname, midd @classmethod def getlatestprofilebyapplicantid(cls, applicantid): schema = FOIRequestApplicantSchema(many=False) - sq = db.session.query(FOIRequestApplicant.applicantprofileid).filter_by(foirequestapplicantid=applicantid) - query = db.session.query(FOIRequestApplicant).filter(FOIRequestApplicant.applicantprofileid.in_(sq)).order_by(FOIRequestApplicant.foirequestapplicantid.desc()).first() + sq = db.session.query(FOIRequestApplicant).filter_by(foirequestapplicantid=applicantid).first() + if not sq.applicantprofileid: + return schema.dump(sq) + query = db.session.query(FOIRequestApplicant).filter(FOIRequestApplicant.applicantprofileid == sq.applicantprofileid).order_by(FOIRequestApplicant.foirequestapplicantid.desc()).first() return schema.dump(query) # Search applicant by id From a6f5dea40b8798431322ed059dc77e8a7800f49d Mon Sep 17 00:00:00 2001 From: Richard Qi Date: Fri, 26 Jan 2024 17:17:43 -0800 Subject: [PATCH 237/238] bug fix --- .../ba218164248e_add_category_to_applicant.py | 18 +++++++++++++ .../request_api/models/FOIMinistryRequests.py | 26 ++++++++++++------- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/request-management-api/migrations/versions/ba218164248e_add_category_to_applicant.py b/request-management-api/migrations/versions/ba218164248e_add_category_to_applicant.py index 73a28fdab..df4acd841 100644 --- a/request-management-api/migrations/versions/ba218164248e_add_category_to_applicant.py +++ b/request-management-api/migrations/versions/ba218164248e_add_category_to_applicant.py @@ -30,12 +30,30 @@ def upgrade(): from ( select max(public."FOIRequestApplicantMappings".foirequestapplicantmappingid) as foirequestapplicantmappingid from public."FOIRequestApplicantMappings" + where public."FOIRequestApplicantMappings".requestortypeid = 1 group by public."FOIRequestApplicantMappings".foirequestapplicantid ) as maxmappingid join public."FOIRequestApplicantMappings" on public."FOIRequestApplicantMappings".foirequestapplicantmappingid = maxmappingid.foirequestapplicantmappingid join public."FOIRequests" on public."FOIRequests".foirequestid = public."FOIRequestApplicantMappings".foirequest_id and public."FOIRequests".version = public."FOIRequestApplicantMappings".foirequestversion_id ) as subquery where public."FOIRequestApplicants".foirequestapplicantid = subquery.foirequestapplicantid + and public."FOIRequestApplicants".foirequestapplicantid not in ( + select foirequestapplicantid from ( + select foirequestapplicantid, count(applicantcategoryid) c from ( + select + public."FOIRequestApplicantMappings".foirequestapplicantid, + public."FOIRequests".applicantcategoryid + from public."FOIRequestApplicantMappings" + join public."FOIRequests" on + public."FOIRequests".foirequestid = public."FOIRequestApplicantMappings".foirequest_id + and public."FOIRequests".version = public."FOIRequestApplicantMappings".foirequestversion_id + where public."FOIRequestApplicantMappings".requestortypeid = 1 + group by public."FOIRequestApplicantMappings".foirequestapplicantid, public."FOIRequests".applicantcategoryid + ) as subquery2 + group by foirequestapplicantid + -- order by count(applicantcategoryid) desc, foirequestapplicantid + ) as subquery1 where c > 1 + ) ''' ) diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index dac8bc5cd..40311402a 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -238,29 +238,35 @@ def getopenrequestsbyapplicantid(cls,applicantid): selectedcolumns = [FOIMinistryRequest.foirequest_id, FOIMinistryRequest.foiministryrequestid] + #aliase for getting applicants by profileid + applicant = aliased(FOIRequestApplicant) + #subquery for getting latest version & proper group/team for FOIMinistryRequest - subquery_applicant_maxid = _session.query(FOIRequestApplicant.applicantprofileid, func.max(FOIRequestApplicant.foirequestapplicantid).label('max_id')).group_by(FOIRequestApplicant.applicantprofileid).subquery() - joincondition_applicant = [ - subquery_applicant_maxid.c.applicantprofileid == FOIRequestApplicant.applicantprofileid, - subquery_applicant_maxid.c.max_id == FOIRequestApplicantMapping.foirequestapplicantid, + subquery_ministry_maxversion = _session.query(FOIMinistryRequest.foirequest_id, func.max(FOIMinistryRequest.foirequestversion_id).label('max_version')).group_by(FOIMinistryRequest.foirequest_id).subquery() + joincondition_ministry = [ + subquery_ministry_maxversion.c.foirequest_id == FOIRequestApplicantMapping.foirequest_id, + subquery_ministry_maxversion.c.max_version == FOIRequestApplicantMapping.foirequestversion_id, ] query = db.session.query( *selectedcolumns ).distinct( FOIMinistryRequest.foiministryrequestid + ).join( + applicant, + applicant.foirequestapplicantid == applicantid, + ).join( + FOIRequestApplicant, + FOIRequestApplicant.applicantprofileid == applicant.applicantprofileid, ).join( FOIRequestApplicantMapping, and_( + FOIRequestApplicantMapping.foirequestapplicantid == FOIRequestApplicant.foirequestapplicantid, FOIRequestApplicantMapping.foirequest_id == FOIMinistryRequest.foirequest_id, - FOIRequestApplicantMapping.foirequestversion_id == FOIMinistryRequest.foirequestversion_id, FOIRequestApplicantMapping.requestortypeid == RequestorType['applicant'].value) ).join( - FOIRequestApplicant, - FOIRequestApplicant.foirequestapplicantid == applicantid, - ).join( - subquery_applicant_maxid, - and_(*joincondition_applicant) + subquery_ministry_maxversion, + and_(*joincondition_ministry) ).filter( # FOIRequestApplicant.foirequestapplicantid == applicantid, FOIMinistryRequest.requeststatusid != 3 From 76768c67dec70aa692ce7a31a384ad98b49d4af2 Mon Sep 17 00:00:00 2001 From: Richard Qi Date: Mon, 29 Jan 2024 12:02:36 -0800 Subject: [PATCH 238/238] fix migration conflicts --- .../versions/59a97f42b5f2_add_profileid_to_applicant.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/request-management-api/migrations/versions/59a97f42b5f2_add_profileid_to_applicant.py b/request-management-api/migrations/versions/59a97f42b5f2_add_profileid_to_applicant.py index 54f46603a..add4b87fc 100644 --- a/request-management-api/migrations/versions/59a97f42b5f2_add_profileid_to_applicant.py +++ b/request-management-api/migrations/versions/59a97f42b5f2_add_profileid_to_applicant.py @@ -11,7 +11,7 @@ # revision identifiers, used by Alembic. revision = '59a97f42b5f2' -down_revision = '7fa7236d06fb' +down_revision = 'b4da31675bd0' branch_labels = None depends_on = None