From d1190e04f45d636d0ee676aa30bf1782ba4bae84 Mon Sep 17 00:00:00 2001 From: divyav-aot Date: Thu, 23 Nov 2023 17:59:15 -0500 Subject: [PATCH 01/22] migration script for statelabel --- .../versions/d185518c3661_ state_label.py | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 request-management-api/migrations/versions/d185518c3661_ state_label.py diff --git a/request-management-api/migrations/versions/d185518c3661_ state_label.py b/request-management-api/migrations/versions/d185518c3661_ state_label.py new file mode 100644 index 000000000..36814855b --- /dev/null +++ b/request-management-api/migrations/versions/d185518c3661_ state_label.py @@ -0,0 +1,47 @@ +"""empty message + +Revision ID: d185518c3661 +Revises: 7fa7236d06fb +Create Date: 2023-06-01 22:31:24.595281 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = 'd185518c3661' +down_revision = '7fa7236d06fb' + +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.execute('ALTER TABLE public."FOIRequestStatuses" ADD COLUMN statuslabel VARCHAR(50);') + op.execute('UPDATE public."FOIRequestStatuses" SET statuslabel = REPLACE(LOWER(name), \' \', \'\');') + op.execute('ALTER TABLE public."FOIRequestStatuses" ALTER COLUMN statuslabel SET NOT NULL;') + op.execute('ALTER TABLE public."FOIRequestStatuses" ADD CONSTRAINT unique_statuslabel UNIQUE (statuslabel);') + + op.execute('ALTER TABLE public."FOIMinistryRequests" ADD COLUMN requeststatuslabel VARCHAR(50);') + op.execute('UPDATE public."FOIMinistryRequests" AS mr SET requeststatuslabel = st.statuslabel FROM public."FOIRequestStatuses" AS st WHERE mr.requeststatusid = st.requeststatusid;') + op.execute('ALTER TABLE public."FOIMinistryRequests" ALTER COLUMN requeststatuslabel SET NOT NULL;') + + op.execute('ALTER TABLE public."FOIRawRequests" ADD COLUMN requeststatuslabel VARCHAR(50);') + op.execute('UPDATE public."FOIRawRequests" SET requeststatuslabel = REPLACE(LOWER(status), \' \', \'\');') + op.execute('ALTER TABLE public."FOIRawRequests" ALTER COLUMN requeststatuslabel SET NOT NULL;') + + op.execute('ALTER TABLE public."FOIRequestTeams" ADD COLUMN requeststatuslabel VARCHAR(50);') + op.execute('UPDATE public."FOIRequestTeams" AS rt SET requeststatuslabel = st.statuslabel FROM public."FOIRequestStatuses" AS st WHERE rt.requeststatusid = st.requeststatusid;') + op.execute('ALTER TABLE public."FOIRequestTeams" ALTER COLUMN requeststatuslabel SET NOT NULL;') + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.execute('ALTER TABLE public."FOIRequestStatuses" drop column statuslabel;') + op.execute('ALTER TABLE public."FOIMinistryRequests" drop column requeststatuslabel;') + op.execute('ALTER TABLE public."FOIRawRequests" drop column requeststatuslabel;') + op.execute('ALTER TABLE public."FOIRequestTeams" drop column requeststatuslabel;') + # ### end Alembic commands ### From 0b07ce84276a17b355e28b56d7815f98eee85eba Mon Sep 17 00:00:00 2001 From: divyav-aot Date: Fri, 24 Nov 2023 15:29:18 -0500 Subject: [PATCH 02/22] statusEnum and migrationscript changes --- .../src/constants/FOI/statusEnum.js | 54 ++++-- .../versions/d185518c3661_ state_label.py | 180 ++++++++++++++++++ 2 files changed, 213 insertions(+), 21 deletions(-) diff --git a/forms-flow-web/src/constants/FOI/statusEnum.js b/forms-flow-web/src/constants/FOI/statusEnum.js index aae8ef2ae..b40603da1 100644 --- a/forms-flow-web/src/constants/FOI/statusEnum.js +++ b/forms-flow-web/src/constants/FOI/statusEnum.js @@ -188,27 +188,39 @@ const MinistryStateList = Object.freeze({ // This corresponds to rows in the FOIRequestStatuses table on the backend const StateEnum = Object.freeze({ - open: { name: "Open", id: 1 }, - callforrecords: { name: "Call For Records", id: 2 }, - callforrecordsoverdue: { name: "Call For Records Overdue", id: -100 }, - closed: { name: "Closed", id: 3 }, - redirect: { name: "Redirect", id: 4 }, - unopened: { name: "Unopened", id: 5 }, - intakeinprogress: { name: "Intake in Progress", id: 6 }, - review: { name: "Records Review", id: 7 }, - feeassessed: { name: "Fee Estimate", id: 8 }, - consult: { name: "Consult", id: 9 }, - signoff: { name: "Ministry Sign Off", id: 10 }, - onhold: { name: "On Hold", id: 11 }, - deduplication: { name: "Deduplication", id: 12 }, - harms: { name: "Harms Assessment", id: 13 }, - response: { name: "Response", id: 14 }, - archived: { name: "Archived", id: 15 }, - peerreview: { name: "Peer Review", id: 16 }, - tagging: { name: "Tagging", id: 17 }, - readytoscan: { name: "Ready to Scan", id: 18 }, - appfeeowing: { name: "App Fee Owing", id: 19 }, - section5pending: { name: "Section 5 Pending", id: 20 }, + open: { name: "Open", id: 1, label: "open" }, + callforrecords: { name: "Call For Records", id: 2, label: "callforrecords" }, + callforrecordsoverdue: { + name: "Call For Records Overdue", + id: -100, + label: "callforrecordsoverdue", + }, + closed: { name: "Closed", id: 3, label: "closed" }, + redirect: { name: "Redirect", id: 4, label: "redirect" }, + unopened: { name: "Unopened", id: 5, label: "unopened" }, + intakeinprogress: { + name: "Intake in Progress", + id: 6, + label: "intakeinprogress", + }, + review: { name: "Records Review", id: 7, label: "recordsreview" }, + feeassessed: { name: "Fee Estimate", id: 8, label: "feeestimate" }, + consult: { name: "Consult", id: 9, label: "consult" }, + signoff: { name: "Ministry Sign Off", id: 10, label: "ministrysignoff" }, + onhold: { name: "On Hold", id: 11, label: "onhold" }, + deduplication: { name: "Deduplication", id: 12, label: "deduplication" }, + harms: { name: "Harms Assessment", id: 13, label: "harmsassessment" }, + response: { name: "Response", id: 14, label: "response" }, + archived: { name: "Archived", id: 15, label: "archived" }, + peerreview: { name: "Peer Review", id: 16, label: "peerreview" }, + tagging: { name: "Tagging", id: 17, label: "tagging" }, + readytoscan: { name: "Ready to Scan", id: 18, label: "readytoscan" }, + appfeeowing: { name: "App Fee Owing", id: 19, label: "appfeeowing" }, + section5pending: { + name: "Section 5 Pending", + id: 20, + label: "section5pending", + }, }); const StateTransitionCategories = Object.freeze({ diff --git a/request-management-api/migrations/versions/d185518c3661_ state_label.py b/request-management-api/migrations/versions/d185518c3661_ state_label.py index 36814855b..9b1dd55ae 100644 --- a/request-management-api/migrations/versions/d185518c3661_ state_label.py +++ b/request-management-api/migrations/versions/d185518c3661_ state_label.py @@ -27,14 +27,103 @@ def upgrade(): op.execute('ALTER TABLE public."FOIMinistryRequests" ADD COLUMN requeststatuslabel VARCHAR(50);') op.execute('UPDATE public."FOIMinistryRequests" AS mr SET requeststatuslabel = st.statuslabel FROM public."FOIRequestStatuses" AS st WHERE mr.requeststatusid = st.requeststatusid;') op.execute('ALTER TABLE public."FOIMinistryRequests" ALTER COLUMN requeststatuslabel SET NOT NULL;') + op.execute('DROP INDEX "FOIMinistryRequests_event";') + op.execute('CREATE INDEX "FOIMinistryRequests_event" ON "FOIMinistryRequests"(axisrequestid, assignedto, assignedgroup, assignedministryperson, assignedministrygroup, requeststatusid, requeststatuslabel);') op.execute('ALTER TABLE public."FOIRawRequests" ADD COLUMN requeststatuslabel VARCHAR(50);') op.execute('UPDATE public."FOIRawRequests" SET requeststatuslabel = REPLACE(LOWER(status), \' \', \'\');') op.execute('ALTER TABLE public."FOIRawRequests" ALTER COLUMN requeststatuslabel SET NOT NULL;') + op.execute('DROP INDEX "FOIRawRequests_event";') + op.execute('CREATE INDEX "FOIRawRequests_event" ON "FOIRawRequests" (axisrequestid, assignedto, assignedgroup, status, requeststatuslabel);') op.execute('ALTER TABLE public."FOIRequestTeams" ADD COLUMN requeststatuslabel VARCHAR(50);') op.execute('UPDATE public."FOIRequestTeams" AS rt SET requeststatuslabel = st.statuslabel FROM public."FOIRequestStatuses" AS st WHERE rt.requeststatusid = st.requeststatusid;') op.execute('ALTER TABLE public."FOIRequestTeams" ALTER COLUMN requeststatuslabel SET NOT NULL;') + + + op.execute(""" +CREATE OR REPLACE VIEW public."v_FOIRequests" +AS SELECT DISTINCT ON (fr.foiministryrequestid) fr.foiministryrequestid, + fr.version, + fr.axisrequestid, + fr.foirequest_id, + NULL::text AS rawrequestid, + fr.assignedto, + fr.assignedgroup, + fr.assignedministryperson, + fr.assignedministrygroup, + CASE + WHEN asg.lastname IS NOT NULL AND asg.firstname IS NOT NULL THEN ((asg.lastname::text || ', '::text) || asg.firstname::text)::character varying + WHEN asg.lastname IS NOT NULL AND asg.firstname IS NULL THEN asg.lastname + WHEN asg.lastname IS NULL AND asg.firstname IS NOT NULL THEN asg.firstname + ELSE coalesce(fr.assignedto, fr.assignedgroup) + END AS assignedtoformatted, + CASE + WHEN msg.lastname IS NOT NULL AND msg.firstname IS NOT NULL THEN ((msg.lastname::text || ', '::text) || msg.firstname::text)::character varying + WHEN msg.lastname IS NOT NULL AND msg.firstname IS NULL THEN msg.lastname + WHEN msg.lastname IS NULL AND msg.firstname IS NOT NULL THEN msg.firstname + ELSE coalesce(fr.assignedministryperson, fr.assignedministrygroup) + END AS ministryassignedtoformatted, + fr.requeststatusid, + fs2.name AS status, + fr.description, to_char(fr.created_at,'YYYYMMDDHH24MMSSMSUS') crtid, + fr.requeststatuslabel AS requeststatuslabel + FROM "FOIMinistryRequests" fr + JOIN "FOIRequestStatuses" fs2 ON fr.requeststatusid = fs2.requeststatusid + LEFT JOIN "FOIAssignees" asg ON fr.assignedto::text = asg.username::text + LEFT JOIN "FOIAssignees" msg ON fr.assignedministryperson::text = msg.username::text + ORDER BY fr.foiministryrequestid, fr.version DESC, fr.axisrequestid; +""") + op.execute(""" +CREATE OR REPLACE VIEW public."v_FOIRawRequests" +AS SELECT tmp.requestid::text AS rawrequestid, + tmp.axisrequestid, + tmp.foirequest_id, + tmp.ministryrequestid, + tmp.assignedto, + tmp.assignedgroup, + tmp.assignedministryperson, + tmp.assignedministrygroup, + tmp.assignedtoformatted, + tmp.ministryassignedtoformatted, + tmp.status, + tmp.description, + tmp.isiaorestricted, + tmp.crtid + FROM ( SELECT DISTINCT ON (fr.requestid) fr.requestid, + fr.version, + CASE + WHEN fr.axisrequestid IS NULL THEN ('U-00'::text || fr.requestid)::character varying + ELSE fr.axisrequestid + END AS axisrequestid, + NULL::integer AS foirequest_id, + NULL::integer AS ministryrequestid, + fr.assignedto, + fr.assignedgroup, + NULL::text AS assignedministryperson, + NULL::text AS assignedministrygroup, + CASE + WHEN asg.lastname IS NOT NULL AND asg.firstname IS NOT NULL THEN ((asg.lastname::text || ', '::text) || asg.firstname::text)::character varying + WHEN asg.lastname IS NOT NULL AND asg.firstname IS NULL THEN asg.lastname + WHEN asg.lastname IS NULL AND asg.firstname IS NOT NULL THEN asg.firstname + ELSE coalesce(fr.assignedto, fr.assignedgroup) + END AS assignedtoformatted, + NULL::text AS ministryassignedtoformatted, + fr.status, + CASE + WHEN fr.status::text = 'Unopened'::text THEN (fr.requestrawdata -> 'descriptionTimeframe'::text) ->> 'description'::text + ELSE fr.requestrawdata ->> 'description'::text + END AS description, + fr.isiaorestricted, to_char(fr.created_at,'YYYYMMDDHH24MMSSMSUS') crtid + FROM "FOIRawRequests" fr + LEFT JOIN "FOIAssignees" asg ON fr.assignedto::text = asg.username::text + WHERE NOT (fr.axisrequestid::text IN ( SELECT "v_FOIRequests".axisrequestid + FROM "v_FOIRequests" + WHERE "v_FOIRequests".requeststatuslabel = 'closed')) + ORDER BY fr.requestid, fr.version DESC, fr.axisrequestid) tmp + WHERE tmp.status::text <> ALL (ARRAY['Archived'::character varying, 'Unopened'::character varying, 'Closed'::character varying]::text[]); +""") + # ### end Alembic commands ### @@ -44,4 +133,95 @@ def downgrade(): op.execute('ALTER TABLE public."FOIMinistryRequests" drop column requeststatuslabel;') op.execute('ALTER TABLE public."FOIRawRequests" drop column requeststatuslabel;') op.execute('ALTER TABLE public."FOIRequestTeams" drop column requeststatuslabel;') + + op.execute('DROP INDEX "FOIMinistryRequests_event";') + op.execute('CREATE INDEX "FOIMinistryRequests_event" ON "FOIMinistryRequests"(axisrequestid, assignedto, assignedgroup, assignedministryperson, assignedministrygroup, requeststatusid);') + + op.execute('DROP INDEX "FOIRawRequests_event";') + op.execute('CREATE INDEX "FOIRawRequests_event" ON "FOIRawRequests" (axisrequestid, assignedto, assignedgroup, status);') + + op.execute('DROP VIEW public."v_FOIRawRequests";') + op.execute('DROP VIEW public."v_FOIRequests";') + + op.execute(""" +CREATE OR REPLACE VIEW public."v_FOIRequests" +AS SELECT DISTINCT ON (fr.foiministryrequestid) fr.foiministryrequestid, + fr.version, + fr.axisrequestid, + fr.foirequest_id, + NULL::text AS rawrequestid, + fr.assignedto, + fr.assignedgroup, + fr.assignedministryperson, + fr.assignedministrygroup, + CASE + WHEN asg.lastname IS NOT NULL AND asg.firstname IS NOT NULL THEN ((asg.lastname::text || ', '::text) || asg.firstname::text)::character varying + WHEN asg.lastname IS NOT NULL AND asg.firstname IS NULL THEN asg.lastname + WHEN asg.lastname IS NULL AND asg.firstname IS NOT NULL THEN asg.firstname + ELSE coalesce(fr.assignedto, fr.assignedgroup) + END AS assignedtoformatted, + CASE + WHEN msg.lastname IS NOT NULL AND msg.firstname IS NOT NULL THEN ((msg.lastname::text || ', '::text) || msg.firstname::text)::character varying + WHEN msg.lastname IS NOT NULL AND msg.firstname IS NULL THEN msg.lastname + WHEN msg.lastname IS NULL AND msg.firstname IS NOT NULL THEN msg.firstname + ELSE coalesce(fr.assignedministryperson, fr.assignedministrygroup) + END AS ministryassignedtoformatted, + fr.requeststatusid, + fs2.name AS status, + fr.description, to_char(fr.created_at,'YYYYMMDDHH24MMSSMSUS') crtid + FROM "FOIMinistryRequests" fr + JOIN "FOIRequestStatuses" fs2 ON fr.requeststatusid = fs2.requeststatusid + LEFT JOIN "FOIAssignees" asg ON fr.assignedto::text = asg.username::text + LEFT JOIN "FOIAssignees" msg ON fr.assignedministryperson::text = msg.username::text + ORDER BY fr.foiministryrequestid, fr.version DESC, fr.axisrequestid; +""") + op.execute(""" +CREATE OR REPLACE VIEW public."v_FOIRawRequests" +AS SELECT tmp.requestid::text AS rawrequestid, + tmp.axisrequestid, + tmp.foirequest_id, + tmp.ministryrequestid, + tmp.assignedto, + tmp.assignedgroup, + tmp.assignedministryperson, + tmp.assignedministrygroup, + tmp.assignedtoformatted, + tmp.ministryassignedtoformatted, + tmp.status, + tmp.description, + tmp.isiaorestricted, + tmp.crtid + FROM ( SELECT DISTINCT ON (fr.requestid) fr.requestid, + fr.version, + CASE + WHEN fr.axisrequestid IS NULL THEN ('U-00'::text || fr.requestid)::character varying + ELSE fr.axisrequestid + END AS axisrequestid, + NULL::integer AS foirequest_id, + NULL::integer AS ministryrequestid, + fr.assignedto, + fr.assignedgroup, + NULL::text AS assignedministryperson, + NULL::text AS assignedministrygroup, + CASE + WHEN asg.lastname IS NOT NULL AND asg.firstname IS NOT NULL THEN ((asg.lastname::text || ', '::text) || asg.firstname::text)::character varying + WHEN asg.lastname IS NOT NULL AND asg.firstname IS NULL THEN asg.lastname + WHEN asg.lastname IS NULL AND asg.firstname IS NOT NULL THEN asg.firstname + ELSE coalesce(fr.assignedto, fr.assignedgroup) + END AS assignedtoformatted, + NULL::text AS ministryassignedtoformatted, + fr.status, + CASE + WHEN fr.status::text = 'Unopened'::text THEN (fr.requestrawdata -> 'descriptionTimeframe'::text) ->> 'description'::text + ELSE fr.requestrawdata ->> 'description'::text + END AS description, + fr.isiaorestricted, to_char(fr.created_at,'YYYYMMDDHH24MMSSMSUS') crtid + FROM "FOIRawRequests" fr + LEFT JOIN "FOIAssignees" asg ON fr.assignedto::text = asg.username::text + WHERE NOT (fr.axisrequestid::text IN ( SELECT "v_FOIRequests".axisrequestid + FROM "v_FOIRequests" + WHERE "v_FOIRequests".requeststatusid = 3)) + ORDER BY fr.requestid, fr.version DESC, fr.axisrequestid) tmp + WHERE tmp.status::text <> ALL (ARRAY['Archived'::character varying, 'Unopened'::character varying, 'Closed'::character varying]::text[]); +""") # ### end Alembic commands ### From 0e7d832bce58974a9ba5fc77895329e9f4248e2a Mon Sep 17 00:00:00 2001 From: divyav-aot Date: Mon, 27 Nov 2023 11:49:30 -0500 Subject: [PATCH 03/22] stateEnum changes to FE and BE --- .../IAO/AdvancedSearch/SearchComponent.js | 35 ++++----- .../AdvancedSearch/SearchComponent.js | 27 ++++--- .../FOIRequest/AxisDetails/AxisSyncModal.js | 5 +- .../FOI/FOIRequest/BottomButtonGroup/index.js | 14 ++-- .../components/FOI/FOIRequest/FOIRequest.js | 4 +- .../MinistryReview/BottomButtonGroup.js | 22 +++--- .../FOI/FOIRequest/RequestDetails.js | 2 +- .../src/components/FOI/FOIRequest/utils.js | 6 +- .../ConfirmationModal/index.js | 24 +++--- .../ConfirmationModal/util.js | 6 +- .../src/constants/FOI/statusEnum.js | 54 +++++-------- .../request_api/models/FOIMinistryRequests.py | 77 ++++++++++--------- .../request_api/models/FOIRawRequests.py | 55 ++++++------- .../models/FOIRequestNotificationUsers.py | 6 +- .../request_api/models/FOIRequestStatus.py | 9 ++- .../request_api/models/FOIRequestTeams.py | 16 ++-- .../request_api/models/views/FOIRequests.py | 1 + .../request_api/resources/foirequest.py | 3 +- .../request_api/resources/request.py | 9 ++- .../request_api/schemas/foirequestwrapper.py | 2 + .../request_api/services/events/state.py | 27 ++++--- .../foirequest/requestservicebuilder.py | 25 ++++-- .../foirequest/requestserviceconfigurator.py | 4 +- .../foirequest/requestservicecreate.py | 9 ++- .../foirequest/requestservicegetter.py | 9 ++- .../requestserviceministrybuilder.py | 16 +++- .../foirequest/requestserviceupdate.py | 2 +- .../rawrequest/rawrequestservicegetter.py | 16 ++-- .../request_api/services/rawrequestservice.py | 15 ++-- .../request_api/services/requestservice.py | 20 ++--- .../request_api/services/workflowservice.py | 2 +- .../request_api/utils/enums.py | 11 ++- 32 files changed, 287 insertions(+), 246 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..25c7e352b 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 @@ -128,15 +128,14 @@ const AdvancedSearch = ({ userDetail }) => { }); const intitialRequestState = { - [StateEnum.unopened.id]: false, - [StateEnum.open.id]: false, - [StateEnum.callforrecords.id]: false, - [StateEnum.review.id]: false, - [StateEnum.signoff.id]: false, - [StateEnum.closed.id]: false, - [StateEnum.callforrecordsoverdue.id]: false + [StateEnum.unopened.label]: false, + [StateEnum.open.label]: false, + [StateEnum.callforrecords.label]: false, + [StateEnum.review.label]: false, + [StateEnum.signoff.label]: false, + [StateEnum.closed.label]: false, + [StateEnum.callforrecordsoverdue.label]: false }; - const [requestState, setRequestState] = useState(() => { if (Object.keys(advancedSearchParams).length > 0 && advancedSearchParams.requestState.length > 0) { let savedRequestState = {...intitialRequestState} @@ -579,9 +578,9 @@ const AdvancedSearch = ({ userDetail }) => { } @@ -593,9 +592,9 @@ const AdvancedSearch = ({ userDetail }) => { } @@ -607,9 +606,9 @@ const AdvancedSearch = ({ userDetail }) => { } @@ -621,9 +620,9 @@ const AdvancedSearch = ({ userDetail }) => { } @@ -635,9 +634,9 @@ const AdvancedSearch = ({ userDetail }) => { } 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..83325ebde 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 @@ -127,13 +127,12 @@ const AdvancedSearch = ({ userDetail }) => { }); const intitialRequestState = { - [StateEnum.callforrecords.id]: false, - [StateEnum.review.id]: false, - [StateEnum.signoff.id]: false, - [StateEnum.closed.id]: false, - [StateEnum.callforrecordsoverdue.id]: false + [StateEnum.callforrecords.label]: false, + [StateEnum.review.label]: false, + [StateEnum.signoff.label]: false, + [StateEnum.closed.label]: false, + [StateEnum.callforrecordsoverdue.label]: false }; - const [requestState, setRequestState] = useState(() => { if (Object.keys(advancedSearchParams).length > 0 && advancedSearchParams.requestState.length > 0) { let savedRequestState = {...intitialRequestState} @@ -592,9 +591,9 @@ const AdvancedSearch = ({ userDetail }) => { } @@ -606,9 +605,9 @@ const AdvancedSearch = ({ userDetail }) => { } @@ -620,9 +619,9 @@ const AdvancedSearch = ({ userDetail }) => { } @@ -634,9 +633,9 @@ const AdvancedSearch = ({ userDetail }) => { } diff --git a/forms-flow-web/src/components/FOI/FOIRequest/AxisDetails/AxisSyncModal.js b/forms-flow-web/src/components/FOI/FOIRequest/AxisDetails/AxisSyncModal.js index 57b1ef567..df288a2a5 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/AxisDetails/AxisSyncModal.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/AxisDetails/AxisSyncModal.js @@ -298,8 +298,9 @@ const AxisSyncModal = ({ axisSyncModalOpen, setAxisSyncModalOpen, saveRequestObj const saveAxisData = async () => { - if (urlIndexCreateRequest > -1) - updatedSaveReqObj.requeststatusid = StateEnum.intakeinprogress.id; + if (urlIndexCreateRequest > -1) { + updatedSaveReqObj.requeststatuslabel = StateEnum.intakeinprogress.label; + } dispatch(saveRequestDetails(updatedSaveReqObj, urlIndexCreateRequest,requestId,ministryId, (err, res) => { if (!err) { 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..e7bb8b0b5 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/BottomButtonGroup/index.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/BottomButtonGroup/index.js @@ -115,7 +115,7 @@ const BottomButtonGroup = React.memo( const saveRequest = async (setLoader = false) => { if (urlIndexCreateRequest > -1) { - saveRequestObject.requeststatusid = StateEnum.intakeinprogress.id; + saveRequestObject.requeststatuslabel = StateEnum.intakeinprogress.label; setIsAddRequest(false); } dispatch(setFOILoader(setLoader)) @@ -176,7 +176,7 @@ const BottomButtonGroup = React.memo( if ( currentSelectedStatus && currentSelectedStatus !== StateEnum.open.name && - saveRequestObject.requeststatusid && + saveRequestObject.requeststatuslabel && saveRequestObject.currentState ) { //scanning team - MSD/CFD personal @@ -200,7 +200,7 @@ const BottomButtonGroup = React.memo( } saveRequestModal(); } else { - saveRequestObject.requeststatusid = StateEnum.open.id; + saveRequestObject.requeststatuslabel = StateEnum.open.label; if (currentSelectedStatus === StateEnum.open.name && ministryId) { saveRequestModal(); } @@ -231,7 +231,7 @@ const BottomButtonGroup = React.memo( saveRequestObject.id = saveRequestObject.id ? saveRequestObject.id : requestId; - saveRequestObject.requeststatusid = 1; + saveRequestObject.requeststatuslabel = StateEnum.open.label; setOpenModal(true); }; @@ -292,14 +292,14 @@ const BottomButtonGroup = React.memo( if (currentSelectedStatus) { switch (currentSelectedStatus) { case StateEnum.closed.name: - saveRequestObject.requeststatusid = StateEnum.closed.id; + saveRequestObject.requeststatuslabel = StateEnum.closed.label; saveRequestObject.closedate = closingDate; saveRequestObject.closereasonid = closingReasonId; break; case StateEnum.callforrecords.name: saveRequestObject.paymentExpiryDate = "" - saveRequestObject.requeststatusid = StateEnum.callforrecords.id; + saveRequestObject.requeststatuslabel = StateEnum.callforrecords.label; if ( !("cfrDueDate" in saveRequestObject) || saveRequestObject.cfrDueDate === "" @@ -354,7 +354,7 @@ const BottomButtonGroup = React.memo( const status = Object.values(StateEnum).find( (statusValue) => statusValue.name === currentSelectedStatus ); - saveRequestObject.requeststatusid = status.id; + saveRequestObject.requeststatuslabel = status.label; if (currentSelectedStatus === StateEnum.onhold.name && !saveRequestObject.paymentExpiryDate) { saveRequestObject.paymentExpiryDate = dueDateCalculation(new Date(), PAYMENT_EXPIRY_DAYS); } diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index d754731d2..1da3db7ab 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -301,8 +301,8 @@ const FOIRequest = React.memo(({ userDetail }) => { const assignedTo = getAssignedTo(requestDetails); setAssignedToValue(assignedTo); if (Object.entries(requestDetails)?.length !== 0) { - let requestStateFromId = findRequestState(requestDetails.requeststatusid) - ? findRequestState(requestDetails.requeststatusid) + let requestStateFromId = findRequestState(requestDetails.requeststatuslabel) + ? findRequestState(requestDetails.requeststatuslabel) : StateEnum.unopened.name; setRequestState(requestStateFromId); settabStatus(requestStateFromId); diff --git a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/BottomButtonGroup.js b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/BottomButtonGroup.js index 1d2ef577e..14fd9def1 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/BottomButtonGroup.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/BottomButtonGroup.js @@ -186,34 +186,34 @@ const BottomButtonGroup = React.memo( const [successCount, setSuccessCount] = useState(0); const [fileCount, setFileCount] = useState(0); const [documents, setDocuments] = useState([]); - + const saveStatusId = () => { if (currentSelectedStatus) { switch (currentSelectedStatus.toLowerCase()) { case StateEnum.review.name.toLowerCase(): - saveMinistryRequestObject.requeststatusid = StateEnum.review.id; + saveMinistryRequestObject.requeststatuslabel = StateEnum.review.label; break; case StateEnum.feeassessed.name.toLowerCase(): - saveMinistryRequestObject.requeststatusid = - StateEnum.feeassessed.id; + saveMinistryRequestObject.requeststatuslabel = + StateEnum.feeassessed.label; break; case StateEnum.deduplication.name.toLowerCase(): - saveMinistryRequestObject.requeststatusid = - StateEnum.deduplication.id; + saveMinistryRequestObject.requeststatuslabel = + StateEnum.deduplication.label; break; case StateEnum.harms.name.toLowerCase(): - saveMinistryRequestObject.requeststatusid = StateEnum.harms.id; + saveMinistryRequestObject.requeststatuslabel = StateEnum.harms.label; break; case StateEnum.signoff.name.toLowerCase(): - saveMinistryRequestObject.requeststatusid = StateEnum.signoff.id; + saveMinistryRequestObject.requeststatuslabel = StateEnum.signoff.label; break; case StateEnum.response.name.toLowerCase(): saveMinistryRequestObject.ministrysignoffapproval = ministryApprovalState; - saveMinistryRequestObject.requeststatusid = StateEnum.response.id; + saveMinistryRequestObject.requeststatuslabel = StateEnum.response.label; break; case StateEnum.callforrecords.name.toLowerCase(): - saveMinistryRequestObject.requeststatusid = - StateEnum.callforrecords.id; + saveMinistryRequestObject.requeststatuslabel = + StateEnum.callforrecords.label; break; } } diff --git a/forms-flow-web/src/components/FOI/FOIRequest/RequestDetails.js b/forms-flow-web/src/components/FOI/FOIRequest/RequestDetails.js index 03f3005ef..43e4b4ae1 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/RequestDetails.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/RequestDetails.js @@ -126,7 +126,7 @@ const RequestDetails = React.memo( receivedDate: !!receivedDate ? formatDate(receivedDate): "", requestStartDate: startDate ? formatDate(startDate): "", dueDate: validateFields(requestDetails, FOI_COMPONENT_CONSTANTS.DUE_DATE, startDate ? formatDate(startDate): ""), - requestState: findRequestState(requestDetails?.requeststatusid) + requestState: findRequestState(requestDetails?.requeststatuslabel) } //event bubble up - sets the initial value to validate the required fields handleRequestDetailsInitialValue(requestDetailsObject); diff --git a/forms-flow-web/src/components/FOI/FOIRequest/utils.js b/forms-flow-web/src/components/FOI/FOIRequest/utils.js index f4aa33500..1ed724913 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/utils.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/utils.js @@ -359,10 +359,10 @@ export const alertUser = (e) => { e.returnValue = ""; }; -export const findRequestState = (requestStatusId) => { - if (requestStatusId != undefined) { +export const findRequestState = (requestStatusLabel) => { + if (requestStatusLabel != undefined) { let stateArray = Object.entries(StateEnum).find( - (value) => value[1].id === requestStatusId + (value) => value[1].label === requestStatusLabel ); return stateArray[1].name; } diff --git a/forms-flow-web/src/components/FOI/customComponents/ConfirmationModal/index.js b/forms-flow-web/src/components/FOI/customComponents/ConfirmationModal/index.js index a0ffb50ff..e727e9b4d 100644 --- a/forms-flow-web/src/components/FOI/customComponents/ConfirmationModal/index.js +++ b/forms-flow-web/src/components/FOI/customComponents/ConfirmationModal/index.js @@ -133,8 +133,8 @@ export default function ConfirmationModal({requestId, openModal, handleModal, st ( state.toLowerCase() === StateEnum.onhold.name.toLowerCase() && ( - saveRequestObject.requeststatusid === StateEnum.feeassessed.id - || saveRequestObject.requeststatusid === StateEnum.response.id + saveRequestObject.requeststatuslabel === StateEnum.feeassessed.label + || saveRequestObject.requeststatuslabel === StateEnum.response.label ) && saveRequestObject.email) ) @@ -150,22 +150,22 @@ export default function ConfirmationModal({requestId, openModal, handleModal, st let fileStatusTransition = ""; if (state.toLowerCase() === StateEnum.response.name.toLowerCase()) fileStatusTransition = StateTransitionCategories.signoffresponse.name; - else if (saveRequestObject.requeststatusid === StateEnum.callforrecords.id + else if (saveRequestObject.requeststatuslabel === StateEnum.callforrecords.label && state.toLowerCase() === StateEnum.review.name.toLowerCase()) fileStatusTransition = StateTransitionCategories.cfrreview.name; - else if (saveRequestObject.requeststatusid === StateEnum.harms.id + else if (saveRequestObject.requeststatuslabel === StateEnum.harms.label && state.toLowerCase() === StateEnum.review.name.toLowerCase()) fileStatusTransition = StateTransitionCategories.harmsreview.name; - else if (saveRequestObject.requeststatusid === StateEnum.feeassessed.id + else if (saveRequestObject.requeststatuslabel === StateEnum.feeassessed.label && state.toLowerCase() === StateEnum.onhold.name.toLowerCase()) fileStatusTransition = StateTransitionCategories.feeonhold.name; - else if (saveRequestObject.requeststatusid === StateEnum.response.id + else if (saveRequestObject.requeststatuslabel === StateEnum.response.label && state.toLowerCase() === StateEnum.onhold.name.toLowerCase()) fileStatusTransition = StateTransitionCategories.responseonhold.name; - else if (saveRequestObject.requeststatusid === StateEnum.response.id + else if (saveRequestObject.requeststatuslabel === StateEnum.response.label && state.toLowerCase() === StateEnum.review.name.toLowerCase()) fileStatusTransition = StateTransitionCategories.responsereview.name; - else if (saveRequestObject.requeststatusid === StateEnum.signoff.id + else if (saveRequestObject.requeststatuslabel === StateEnum.signoff.label && state.toLowerCase() === StateEnum.review.name.toLowerCase()) fileStatusTransition = StateTransitionCategories.signoffreview.name; @@ -206,7 +206,7 @@ export default function ConfirmationModal({requestId, openModal, handleModal, st (state.toLowerCase() === StateEnum.review.name.toLowerCase() && (!isAnyAmountPaid || !isMinistry)) || (state.toLowerCase() === StateEnum.onhold.name.toLowerCase() - && (saveRequestObject.requeststatusid === StateEnum.feeassessed.id || saveRequestObject.requeststatusid === StateEnum.response.id) + && (saveRequestObject.requeststatuslabel === StateEnum.feeassessed.label || saveRequestObject.requeststatuslabel === StateEnum.response.label) && saveRequestObject.email && cfrStatus == 'approved' && amountDue !== 0) @@ -226,7 +226,7 @@ export default function ConfirmationModal({requestId, openModal, handleModal, st ); } - else if (currentState?.toLowerCase() === StateEnum.signoff.name.toLowerCase() && state.toLowerCase() === StateEnum.response.name.toLowerCase() && saveRequestObject.requeststatusid === StateEnum.signoff.id) { + else if (currentState?.toLowerCase() === StateEnum.signoff.name.toLowerCase() && state.toLowerCase() === StateEnum.response.name.toLowerCase() && saveRequestObject.requeststatuslabel === StateEnum.signoff.label) { return (
@@ -312,7 +312,7 @@ export default function ConfirmationModal({requestId, openModal, handleModal, st
@@ -331,7 +331,7 @@ export default function ConfirmationModal({requestId, openModal, handleModal, st
diff --git a/forms-flow-web/src/components/FOI/customComponents/ConfirmationModal/util.js b/forms-flow-web/src/components/FOI/customComponents/ConfirmationModal/util.js index c24c79a58..5cd9c4e31 100644 --- a/forms-flow-web/src/components/FOI/customComponents/ConfirmationModal/util.js +++ b/forms-flow-web/src/components/FOI/customComponents/ConfirmationModal/util.js @@ -67,9 +67,9 @@ import { getFullnameList } from "../../../../helper/FOI/helper"; case StateEnum.review.name.toLowerCase(): if(!allowStateChange) return {title: "Changing the state", body: `Unable to change state until fee estimate actuals have been completed.`}; - else if (!isAnyAmountPaid && _saveRequestObject.requeststatusid === StateEnum.callforrecords.id) + else if (!isAnyAmountPaid && _saveRequestObject.requeststatuslabel === StateEnum.callforrecords.label) return {title: "Review Request", body: `Upload completed Call for Records form (if required) to change the state.`}; - else if (_saveRequestObject.requeststatusid === StateEnum.harms.id) + else if (_saveRequestObject.requeststatuslabel === StateEnum.harms.label) return {title: "Review Request", body: `Upload completed Call for Records form (if required) to change the state.`}; else return {title: "Changing the state", body: `Are you sure you want to change Request #${_requestNumber} to ${StateEnum.review.name}?`}; @@ -122,7 +122,7 @@ import { getFullnameList } from "../../../../helper/FOI/helper"; body: <>Are you sure you want to change Request #{_requestNumber} to on hold?
This will stop the clock and automatically email the applicant the fee estimate. }; } case StateEnum.response.name.toLowerCase(): - if (_saveRequestObject.requeststatusid === StateEnum.signoff.id) + if (_saveRequestObject.requeststatuslabel === StateEnum.signoff.label) return {title: "Ministry Sign Off", body: `Upload eApproval Logs, and enter in required approval fields to verify Ministry Approval and then change the state.`}; else return {title: "Changing the state", body: `Are you sure you want to change Request #${_requestNumber} to ${StateEnum.response.name}?`}; diff --git a/forms-flow-web/src/constants/FOI/statusEnum.js b/forms-flow-web/src/constants/FOI/statusEnum.js index b40603da1..6f226fa09 100644 --- a/forms-flow-web/src/constants/FOI/statusEnum.js +++ b/forms-flow-web/src/constants/FOI/statusEnum.js @@ -188,39 +188,27 @@ const MinistryStateList = Object.freeze({ // This corresponds to rows in the FOIRequestStatuses table on the backend const StateEnum = Object.freeze({ - open: { name: "Open", id: 1, label: "open" }, - callforrecords: { name: "Call For Records", id: 2, label: "callforrecords" }, - callforrecordsoverdue: { - name: "Call For Records Overdue", - id: -100, - label: "callforrecordsoverdue", - }, - closed: { name: "Closed", id: 3, label: "closed" }, - redirect: { name: "Redirect", id: 4, label: "redirect" }, - unopened: { name: "Unopened", id: 5, label: "unopened" }, - intakeinprogress: { - name: "Intake in Progress", - id: 6, - label: "intakeinprogress", - }, - review: { name: "Records Review", id: 7, label: "recordsreview" }, - feeassessed: { name: "Fee Estimate", id: 8, label: "feeestimate" }, - consult: { name: "Consult", id: 9, label: "consult" }, - signoff: { name: "Ministry Sign Off", id: 10, label: "ministrysignoff" }, - onhold: { name: "On Hold", id: 11, label: "onhold" }, - deduplication: { name: "Deduplication", id: 12, label: "deduplication" }, - harms: { name: "Harms Assessment", id: 13, label: "harmsassessment" }, - response: { name: "Response", id: 14, label: "response" }, - archived: { name: "Archived", id: 15, label: "archived" }, - peerreview: { name: "Peer Review", id: 16, label: "peerreview" }, - tagging: { name: "Tagging", id: 17, label: "tagging" }, - readytoscan: { name: "Ready to Scan", id: 18, label: "readytoscan" }, - appfeeowing: { name: "App Fee Owing", id: 19, label: "appfeeowing" }, - section5pending: { - name: "Section 5 Pending", - id: 20, - label: "section5pending", - }, + open: { name: "Open", label: "open" }, + callforrecords: { name: "Call For Records", label: "callforrecords" }, + callforrecordsoverdue: { name: "Call For Records Overdue", label: "callforrecordsoverdue" }, + closed: { name: "Closed", label: "closed" }, + redirect: { name: "Redirect", label: "redirect" }, + unopened: { name: "Unopened", label: "unopened" }, + intakeinprogress: { name: "Intake in Progress", label: "intakeinprogress" }, + review: { name: "Records Review", label: "recordsreview" }, + feeassessed: { name: "Fee Estimate", label: "feeestimate" }, + consult: { name: "Consult", label: "consult" }, + signoff: { name: "Ministry Sign Off", label: "ministrysignoff" }, + onhold: { name: "On Hold", label: "onhold" }, + deduplication: { name: "Deduplication", label: "deduplication" }, + harms: { name: "Harms Assessment", label: "harmsassessment" }, + response: { name: "Response", label: "response" }, + archived: { name: "Archived", label: "archived" }, + peerreview: { name: "Peer Review", label: "peerreview" }, + tagging: { name: "Tagging", label: "tagging" }, + readytoscan: { name: "Ready to Scan", label: "readytoscan" }, + appfeeowing: { name: "App Fee Owing", label: "appfeeowing" }, + section5pending: { name: "Section 5 Pending", label: "section5pending" }, }); const StateTransitionCategories = Object.freeze({ diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index cd6e2a8e9..3a7fed2f9 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 request_api.utils.enums import StateName class FOIMinistryRequest(db.Model): # Name of the table in our database @@ -68,7 +69,7 @@ class FOIMinistryRequest(db.Model): linkedrequests = db.Column(JSON, unique=False, nullable=True) identityverified = db.Column(JSON, unique=False, nullable=True) ministrysignoffapproval = db.Column(JSON, unique=False, nullable=True) - + requeststatuslabel = db.Column(db.String(50), nullable=False) #ForeignKey References @@ -106,13 +107,13 @@ def getrequest(cls,ministryrequestid): return request_schema.dump(query) @classmethod - def getLastStatusUpdateDate(cls,foiministryrequestid,requeststatusid): + def getLastStatusUpdateDate(cls,foiministryrequestid,requeststatuslabel): statusdate = None try: sql = """select created_at from "FOIMinistryRequests" - where foiministryrequestid = :foiministryrequestid and requeststatusid = :requeststatusid + where foiministryrequestid = :foiministryrequestid and requeststatuslabel = :requeststatuslabel order by version desc limit 1;""" - rs = db.session.execute(text(sql), {'foiministryrequestid': foiministryrequestid, 'requeststatusid': requeststatusid}) + rs = db.session.execute(text(sql), {'foiministryrequestid': foiministryrequestid, 'requeststatuslabel': requeststatuslabel}) statusdate = [row[0] for row in rs][0] except Exception as ex: logging.error(ex) @@ -163,11 +164,11 @@ def getrequests(cls, group = None): if group is None: _ministryrequestids = _session.query(distinct(FOIMinistryRequest.foiministryrequestid)).filter(FOIMinistryRequest.isactive == True).all() elif (group == IAOTeamWithKeycloackGroup.flex.value): - _ministryrequestids = _session.query(distinct(FOIMinistryRequest.foiministryrequestid)).filter(and_(FOIMinistryRequest.isactive == True), and_(and_(FOIMinistryRequest.assignedgroup == group),and_(FOIMinistryRequest.requeststatusid.in_([1,2,3,12,13,7,8,9,10,11,14,16,17,18])))).all() + _ministryrequestids = _session.query(distinct(FOIMinistryRequest.foiministryrequestid)).filter(and_(FOIMinistryRequest.isactive == True), and_(and_(FOIMinistryRequest.assignedgroup == group),and_(FOIMinistryRequest.requeststatuslabel.in_([StateName.open.name,StateName.callforrecords.name,StateName.closed.name,StateName.recordsreview.name,StateName.feeestimate.name,StateName.consult.name,StateName.ministrysignoff.value,StateName.onhold.name,StateName.deduplication.name,StateName.harmsassessment.name,StateName.response.name,StateName.peerreview.name,StateName.tagging.name,StateName.readytoscan.name])))).all() elif (group in ProcessingTeamWithKeycloackGroup.list()): - _ministryrequestids = _session.query(distinct(FOIMinistryRequest.foiministryrequestid)).filter(and_(FOIMinistryRequest.isactive == True), and_(and_(FOIMinistryRequest.assignedgroup == group),and_(FOIMinistryRequest.requeststatusid.in_([1,2,3,7,8,9,10,11,14,16,17,18])))).all() + _ministryrequestids = _session.query(distinct(FOIMinistryRequest.foiministryrequestid)).filter(and_(FOIMinistryRequest.isactive == True), and_(and_(FOIMinistryRequest.assignedgroup == group),and_(FOIMinistryRequest.requeststatuslabel.in_([StateName.open.name,StateName.callforrecords.name,StateName.closed.name,StateName.recordsreview.name,StateName.feeestimate.name,StateName.consult.name,StateName.ministrysignoff.value,StateName.onhold.name,StateName.response.name,StateName.peerreview.name,StateName.tagging.name,StateName.readytoscan.name])))).all() else: - _ministryrequestids = _session.query(distinct(FOIMinistryRequest.foiministryrequestid)).filter(and_(FOIMinistryRequest.isactive == True), or_(and_(FOIMinistryRequest.assignedgroup == group),and_(FOIMinistryRequest.assignedministrygroup == group,or_(FOIMinistryRequest.requeststatusid.in_([2,7,9,8,10,11,12,13,14,16,17,18]))))).all() + _ministryrequestids = _session.query(distinct(FOIMinistryRequest.foiministryrequestid)).filter(and_(FOIMinistryRequest.isactive == True), or_(and_(FOIMinistryRequest.assignedgroup == group),and_(FOIMinistryRequest.assignedministrygroup == group,or_(FOIMinistryRequest.requeststatuslabel.in_([StateName.callforrecords.name,StateName.recordsreview.name,StateName.feeestimate.name,StateName.consult.name,StateName.ministrysignoff.name,StateName.onhold.name,StateName.deduplication.name,StateName.harmsassessment.name,StateName.response.name,StateName.peerreview.name,StateName.tagging.name,StateName.readytoscan.name]))))).all() _requests = [] ministryrequest_schema = FOIMinistryRequestSchema() @@ -226,10 +227,11 @@ def getrequestById(cls,ministryrequestid): def getrequeststatusById(cls,ministryrequestid): summary = [] try: - sql = 'select foirequest_id, version, requeststatusid, created_at from "FOIMinistryRequests" fr where foiministryrequestid = :ministryrequestid and requeststatusid != 3 order by version desc;' - rs = db.session.execute(text(sql), {'ministryrequestid': ministryrequestid}) + sql = 'select foirequest_id, version, requeststatusid, requeststatuslabel, created_at from "FOIMinistryRequests" fr where foiministryrequestid = :ministryrequestid and requeststatuslabel != :requeststatuslabel order by version desc;' + + rs = db.session.execute(text(sql), {'ministryrequestid': ministryrequestid, 'requeststatuslabel': StateName.closed.name}) for row in rs: - summary.append({"requeststatusid": row["requeststatusid"], "created_at": row["created_at"], "foirequest_id": row["foirequest_id"]}) + summary.append({"requeststatusid": row["requeststatusid"], "requeststatuslabel": row["requeststatuslabel"], "created_at": row["created_at"], "foirequest_id": row["foirequest_id"]}) except Exception as ex: logging.error(ex) raise ex @@ -406,13 +408,13 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us else_ = FOIMinistryRequest.assignedministrygroup).label('ministryAssignedToFormatted') duedate = case([ - (FOIMinistryRequest.requeststatusid == 11, # On Hold + (FOIMinistryRequest.requeststatuslabel == StateName.onhold.name, # On Hold literal(None)), ], else_ = cast(FOIMinistryRequest.duedate, String)).label('duedate') cfrduedate = case([ - (FOIMinistryRequest.requeststatusid == 11, # On Hold + (FOIMinistryRequest.requeststatuslabel == StateName.onhold.name, # On Hold literal(None)), ], else_ = cast(FOIMinistryRequest.cfrduedate, String)).label('cfrduedate') @@ -553,7 +555,7 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us SubjectCode, SubjectCode.subjectcodeid == FOIMinistryRequestSubjectCode.subjectcodeid, isouter=True - ).filter(FOIMinistryRequest.requeststatusid != 3) + ).filter(FOIMinistryRequest.requeststatuslabel != StateName.closed.name) if(additionalfilter == 'watchingRequests'): #watchby @@ -682,7 +684,7 @@ def getgroupfilters(cls, groups): FOIMinistryRequest.assignedgroup == group, and_( FOIMinistryRequest.assignedgroup == IAOTeamWithKeycloackGroup.flex.value, - FOIMinistryRequest.requeststatusid.in_([1]) + FOIMinistryRequest.requeststatuslabel.in_([StateName.open.name]) ) ) ) @@ -692,7 +694,7 @@ def getgroupfilters(cls, groups): FOIMinistryRequest.assignedgroup == group, and_( FOIMinistryRequest.assignedministrygroup == group, - FOIMinistryRequest.requeststatusid.in_([2,7,9,8,10,11,12,13,14,16,17,18]) + FOIMinistryRequest.requeststatuslabel.in_([StateName.callforrecords.name,StateName.recordsreview.name,StateName.feeestimate.name,StateName.consult.name,StateName.ministrysignoff.name,StateName.onhold.name,StateName.deduplication.name,StateName.harmsassessment.name,StateName.response.name,StateName.peerreview.name,StateName.tagging.name,StateName.readytoscan.name]) ) ) ) @@ -707,7 +709,7 @@ def getgroupfilters(cls, groups): @classmethod def getrequestoriginalduedate(cls,ministryrequestid): - return db.session.query(FOIMinistryRequest.duedate).filter(FOIMinistryRequest.foiministryrequestid == ministryrequestid, FOIMinistryRequest.requeststatusid == 1).order_by(FOIMinistryRequest.version).first()[0] + return db.session.query(FOIMinistryRequest.duedate).filter(FOIMinistryRequest.foiministryrequestid == ministryrequestid, FOIMinistryRequest.requeststatuslabel == StateName.open.name).order_by(FOIMinistryRequest.version).first()[0] @classmethod def getduedate(cls,ministryrequestid): @@ -719,10 +721,10 @@ def getupcomingcfrduerecords(cls): upcomingduerecords = [] try: sql = """select distinct on (filenumber) filenumber, to_char(cfrduedate, 'YYYY-MM-DD') as cfrduedate, foiministryrequestid, version, foirequest_id, created_at, createdby from "FOIMinistryRequests" fpa - where isactive = true and cfrduedate is not null and requeststatusid = 2 + where isactive = true and cfrduedate is not null and requeststatuslabel = :requeststatuslabel and cfrduedate between NOW() - INTERVAL '7 DAY' AND NOW() + INTERVAL '7 DAY' order by filenumber , version desc;""" - rs = db.session.execute(text(sql)) + rs = db.session.execute(text(sql), {'requeststatuslabel': StateName.callforrecords.name}) for row in rs: upcomingduerecords.append({"filenumber": row["filenumber"], "cfrduedate": row["cfrduedate"],"foiministryrequestid": row["foiministryrequestid"], "version": row["version"], "foirequest_id": row["foirequest_id"], "created_at": row["created_at"], "createdby": row["createdby"]}) except Exception as ex: @@ -737,10 +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 requeststatusid not in (5,6,4,11,3,15) + 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;""" - rs = db.session.execute(text(sql)) + rs = db.session.execute(text(sql), {'requeststatuslabel': [StateName.closed.name,StateName.redirect.name,StateName.unopened.name,StateName.intakeinprogress.name,StateName.onhold.name,StateName.archived.name]}) 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"]}) except Exception as ex: @@ -758,14 +760,15 @@ def getupcomingdivisionduerecords(cls): frd.divisionid, frd.stageid, pad2."name" divisionname, pads."name" stagename, to_char(divisionduedate, 'YYYY-MM-DD') as duedate, frd.created_at, frd.createdby from "FOIMinistryRequestDivisions" frd - inner join (select distinct on (fpa.foiministryrequestid) foiministryrequestid, version as foiministryrequestversion, axisrequestid, filenumber, foirequest_id, requeststatusid + 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.requeststatusid not in (5,6,4,11,3,15) + 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;""" - rs = db.session.execute(text(sql)) + rs = db.session.execute(text(sql), {'requeststatuslabel': [StateName.closed.name,StateName.redirect.name,StateName.unopened.name,StateName.intakeinprogress.name,StateName.onhold.name,StateName.archived.name]}) + for row in rs: upcomingduerecords.append({"axisrequestid": row["axisrequestid"], "filenumber": row["filenumber"], "foiministryrequestid": row["foiministryrequestid"], "version": row["foiministryrequestversion"], @@ -849,9 +852,9 @@ def getclosedaxisids(cls): try: sql = """ select distinct on (foiministryrequestid) foiministryrequestid, version, axisrequestid from "FOIMinistryRequests" fr - where requeststatusid = 3 + where requeststatuslabel = :requeststatuslabel order by foiministryrequestid , version desc, axisrequestid""" - rs = db.session.execute(text(sql)) + rs = db.session.execute(text(sql), {'requeststatuslabel': StateName.closed.name}) for row in rs: axisids.append(row["axisrequestid"]) except Exception as ex: @@ -926,13 +929,13 @@ def getbasequery(cls, iaoassignee, ministryassignee, userid=None, requestby='IAO else_ = FOIMinistryRequest.assignedministrygroup).label('ministryAssignedToFormatted') duedate = case([ - (FOIMinistryRequest.requeststatusid == 11, # On Hold + (FOIMinistryRequest.requeststatuslabel == StateName.onhold.name, # On Hold literal(None)), ], else_ = cast(FOIMinistryRequest.duedate, String)).label('duedate') cfrduedate = case([ - (FOIMinistryRequest.requeststatusid == 11, # On Hold + (FOIMinistryRequest.requeststatuslabel == StateName.onhold.name, # On Hold literal(None)), ], else_ = cast(FOIMinistryRequest.cfrduedate, String)).label('cfrduedate') @@ -1116,7 +1119,7 @@ def advancedsearch(cls, params, userid, isministryrestrictedfilemanager = False) groupfilter.append(FOIMinistryRequest.assignedministrygroup == group) #ministry advanced search show cfr onwards - statefilter = FOIMinistryRequest.requeststatusid.in_([2,3,7,9,8,10,11,12,13,14,16,17,18]) + statefilter = FOIMinistryRequest.requeststatuslabel.in_([StateName.callforrecords.name,StateName.closed.name,StateName.recordsreview.name,StateName.feeestimate.name,StateName.consult.name,StateName.ministrysignoff.name,StateName.onhold.name,StateName.deduplication.name,StateName.harmsassessment.name,StateName.response.name,StateName.peerreview.name,StateName.tagging.name,StateName.readytoscan.name]) ministry_queue = FOIMinistryRequest.advancedsearchsubquery(params, iaoassignee, ministryassignee, userid, 'Ministry', False, isministryrestrictedfilemanager).filter(and_(or_(*groupfilter), statefilter)) @@ -1153,10 +1156,10 @@ def getfilterforadvancedsearch(cls, params, iaoassignee, ministryassignee): # return all except closed if(includeclosed == False): - filtercondition.append(FOIMinistryRequest.requeststatusid != 3) + filtercondition.append(FOIMinistryRequest.requeststatuslabel != StateName.closed.name) elif(len(params['requeststatus']) > 1 and includeclosed == False): # return all except closed - filtercondition.append(FOIMinistryRequest.requeststatusid != 3) + filtercondition.append(FOIMinistryRequest.requeststatuslabel != StateName.closed.name) #request type: personal, general if(len(params['requesttype']) > 0): @@ -1185,9 +1188,9 @@ def getfilterforadvancedsearch(cls, params, iaoassignee, ministryassignee): def getfilterforrequeststate(cls, params, includeclosed): #request state: unopened, call for records, etc. requeststatecondition = [] - for stateid in params['requeststate']: - requeststatecondition.append(FOIMinistryRequest.requeststatusid == stateid) - if(stateid == 3): + for statelabel in params['requeststate']: + requeststatecondition.append(FOIMinistryRequest.requeststatuslabel == statelabel) + if(statelabel == StateName.closed.name): includeclosed = True return {'condition': or_(*requeststatecondition), 'includeclosed': includeclosed} @@ -1196,8 +1199,8 @@ def getfilterforrequeststatus(cls, params, iaoassignee, ministryassignee): #request status: overdue || on time if(params['requeststatus'][0] == 'overdue'): #exclude "on hold" for overdue - stateid = 11 - return and_(FOIMinistryRequest.findfield('duedate', iaoassignee, ministryassignee) < datetime.now().date(), FOIMinistryRequest.requeststatusid != stateid) + statelabel = StateName.onhold.name + return and_(FOIMinistryRequest.findfield('duedate', iaoassignee, ministryassignee) < datetime.now().date(), FOIMinistryRequest.requeststatuslabel != statelabel) else: return FOIMinistryRequest.findfield('duedate', iaoassignee, ministryassignee) >= datetime.now().date() @@ -1302,9 +1305,9 @@ def getofflinepaymentflag(cls,ministryrequestid): class FOIMinistryRequestSchema(ma.Schema): class Meta: fields = ('foiministryrequestid','version','filenumber','description','recordsearchfromdate','recordsearchtodate', - 'startdate','duedate','assignedgroup','assignedto','programarea.programareaid','requeststatus.requeststatusid', + 'startdate','duedate','assignedgroup','assignedto','programarea.programareaid', 'foirequest.foirequestid','foirequest.requesttype','foirequest.receiveddate','foirequest.deliverymodeid', - 'foirequest.receivedmodeid','requeststatus.requeststatusid','requeststatus.name','programarea.bcgovcode', + 'foirequest.receivedmodeid','requeststatus.requeststatusid','requeststatuslabel','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') diff --git a/request-management-api/request_api/models/FOIRawRequests.py b/request-management-api/request_api/models/FOIRawRequests.py index 9a0169647..b7588d84c 100644 --- a/request-management-api/request_api/models/FOIRawRequests.py +++ b/request-management-api/request_api/models/FOIRawRequests.py @@ -18,6 +18,7 @@ import logging from dateutil import parser import json +from request_api.utils.enums import StateName class FOIRawRequest(db.Model): # Name of the table in our database @@ -27,6 +28,7 @@ class FOIRawRequest(db.Model): version = db.Column(db.Integer, primary_key=True,nullable=False) requestrawdata = db.Column(JSON, unique=False, nullable=True) status = db.Column(db.String(25), unique=False, nullable=True) + requeststatuslabel = db.Column(db.String(50), unique=False, nullable=False) notes = db.Column(db.String(120), unique=False, nullable=True) wfinstanceid = db.Column(UUID(as_uuid=True), unique=False, nullable=True) assignedgroup = db.Column(db.String(250), unique=False, nullable=True) @@ -55,7 +57,7 @@ class FOIRawRequest(db.Model): @classmethod def saverawrequest(cls, _requestrawdata, sourceofsubmission, ispiiredacted, userid, notes, requirespayment, axisrequestid, axissyncdate, linkedrequests, assigneegroup=None, assignee=None, assigneefirstname=None, assigneemiddlename=None, assigneelastname=None)->DefaultMethodResult: version = 1 - newrawrequest = FOIRawRequest(requestrawdata=_requestrawdata, status = 'Unopened' if sourceofsubmission != "intake" else 'Intake in Progress', createdby=userid, version=version, sourceofsubmission=sourceofsubmission, assignedgroup=assigneegroup, assignedto=assignee, ispiiredacted=ispiiredacted, notes=notes, requirespayment=requirespayment, axisrequestid=axisrequestid, axissyncdate=axissyncdate, linkedrequests=linkedrequests) + newrawrequest = FOIRawRequest(requestrawdata=_requestrawdata, status = StateName.unopened.value if sourceofsubmission != "intake" else StateName.intakeinprogress.value, requeststatuslabel = StateName.unopened.name if sourceofsubmission != "intake" else StateName.intakeinprogress.name, createdby=userid, version=version, sourceofsubmission=sourceofsubmission, assignedgroup=assigneegroup, assignedto=assignee, ispiiredacted=ispiiredacted, notes=notes, requirespayment=requirespayment, axisrequestid=axisrequestid, axissyncdate=axissyncdate, linkedrequests=linkedrequests) if assignee is not None: FOIAssignee.saveassignee(assignee, assigneefirstname, assigneemiddlename, assigneelastname) @@ -66,13 +68,13 @@ def saverawrequest(cls, _requestrawdata, sourceofsubmission, ispiiredacted, user @classmethod def saverawrequest_foipayment(cls,_requestrawdata,notes, requirespayment, ispiiredacted)->DefaultMethodResult: version = 1 - newrawrequest = FOIRawRequest(requestrawdata=_requestrawdata, status='Unopened',createdby=None,version=version,sourceofsubmission="onlineform",assignedgroup=None,assignedto=None,ispiiredacted=ispiiredacted,notes=notes, requirespayment= requirespayment) + newrawrequest = FOIRawRequest(requestrawdata=_requestrawdata, status=StateName.unopened.value, requeststatuslabel = StateName.unopened.name ,createdby=None,version=version,sourceofsubmission="onlineform",assignedgroup=None,assignedto=None,ispiiredacted=ispiiredacted,notes=notes, requirespayment= requirespayment) db.session.add(newrawrequest) db.session.commit() return DefaultMethodResult(True,'Request added',newrawrequest.requestid) @classmethod - def saverawrequestversion(cls,_requestrawdata,requestid,assigneegroup,assignee,status,ispiiredacted,userid,assigneefirstname=None,assigneemiddlename=None,assigneelastname=None)->DefaultMethodResult: + def saverawrequestversion(cls,_requestrawdata,requestid,assigneegroup,assignee,status,ispiiredacted,userid,statuslabel,assigneefirstname=None,assigneemiddlename=None,assigneelastname=None)->DefaultMethodResult: request = db.session.query(FOIRawRequest).filter_by(requestid=requestid).order_by(FOIRawRequest.version.desc()).first() if request is not None: _assginee = assignee if assignee not in (None,'') else None @@ -94,6 +96,7 @@ def saverawrequestversion(cls,_requestrawdata,requestid,assigneegroup,assignee,s updatedby=None, updated_at=datetime.now(), status=status, + requeststatuslabel=statuslabel, assignedgroup=assigneegroup, assignedto=_assginee, wfinstanceid=request.wfinstanceid, @@ -297,7 +300,7 @@ def getDescriptionSummaryById(cls, requestid): requests = [] try: sql = """select * , - CASE WHEN description = (select requestrawdata -> 'descriptionTimeframe' ->> 'description' from "FOIRawRequests" where requestid = :requestid and status = 'Unopened' and version = 1) + CASE WHEN description = (select requestrawdata -> 'descriptionTimeframe' ->> 'description' from "FOIRawRequests" where requestid = :requestid and status = :requeststatus and version = 1) then 'Online Form' else savedby END as createdby from (select CASE WHEN lower(status) <> 'unopened' @@ -312,7 +315,7 @@ def getDescriptionSummaryById(cls, requestid): to_char(created_at, 'YYYY-MM-DD HH24:MI:SS') as createdat, status, ispiiredacted, createdby as savedby from "FOIRawRequests" fr where requestid = :requestid order by version ) as sq;""" - rs = db.session.execute(text(sql), {'requestid': requestid}) + rs = db.session.execute(text(sql), {'requestid': requestid, 'requeststatus': StateName.unopened.value}) for row in rs: requests.append(dict(row)) except Exception as ex: @@ -368,10 +371,10 @@ def getappfeeowingrequests(cls): # with the reminder date sql = ''' SELECT * FROM (SELECT DISTINCT ON (requestid) requestid, updated_at, status FROM public."FOIRawRequests" ORDER BY requestid ASC, version DESC) r - WHERE r.status = 'App Fee Owing' + WHERE r.status = :requeststaus order by r.updated_at asc ''' - rs = db.session.execute(text(sql)) + rs = db.session.execute(text(sql), {'requeststaus': StateName.appfeeowing.value}) appfeeowingrequests = rs except Exception as ex: logging.error(ex) @@ -441,47 +444,47 @@ def getbasequery(cls, additionalfilter=None, userid=None, isiaorestrictedfileman ] requesttype = case([ - (FOIRawRequest.status == 'Unopened', + (FOIRawRequest.status == StateName.unopened.value, FOIRawRequest.requestrawdata['requestType']['requestType'].astext), ], else_ = FOIRawRequest.requestrawdata['requestType'].astext).label('requestType') firstname = case([ - (FOIRawRequest.status == 'Unopened', + (FOIRawRequest.status == StateName.unopened.value, FOIRawRequest.requestrawdata['contactInfo']['firstName'].astext), ], else_ = FOIRawRequest.requestrawdata['firstName'].astext).label('firstName') lastname = case([ - (FOIRawRequest.status == 'Unopened', + (FOIRawRequest.status == StateName.unopened.value, FOIRawRequest.requestrawdata['contactInfo']['lastName'].astext), ], else_ = FOIRawRequest.requestrawdata['lastName'].astext).label('lastName') description = case([ - (FOIRawRequest.status == 'Unopened', + (FOIRawRequest.status == StateName.unopened.value, FOIRawRequest.requestrawdata['descriptionTimeframe']['description'].astext), ], else_ = FOIRawRequest.requestrawdata['description'].astext).label('description') recordsearchfromdate = case([ - (FOIRawRequest.status == 'Unopened', + (FOIRawRequest.status == StateName.unopened.value, FOIRawRequest.requestrawdata['descriptionTimeframe']['fromDate'].astext), ], else_ = FOIRawRequest.requestrawdata['fromDate'].astext).label('recordsearchfromdate') recordsearchtodate = case([ - (FOIRawRequest.status == 'Unopened', + (FOIRawRequest.status == StateName.unopened.value, FOIRawRequest.requestrawdata['descriptionTimeframe']['toDate'].astext), ], else_ = FOIRawRequest.requestrawdata['toDate'].astext).label('recordsearchtodate') duedate = case([ - (FOIRawRequest.status == 'Unopened', + (FOIRawRequest.status == StateName.unopened.value, literal(None)), ], else_ = FOIRawRequest.requestrawdata['dueDate'].astext).label('duedate') receiveddate = case([ - (and_(FOIRawRequest.status == 'Unopened', FOIRawRequest.requestrawdata['receivedDate'].is_(None)), + (and_(FOIRawRequest.status == StateName.unopened.value, FOIRawRequest.requestrawdata['receivedDate'].is_(None)), func.to_char(FOIRawRequest.created_at, 'YYYY-mm-DD')), ], else_ = FOIRawRequest.requestrawdata['receivedDate'].astext).label('receivedDate') receiveddateuf = case([ - (and_(FOIRawRequest.status == 'Unopened', FOIRawRequest.requestrawdata['receivedDateUF'].is_(None)), + (and_(FOIRawRequest.status == StateName.unopened.value, FOIRawRequest.requestrawdata['receivedDateUF'].is_(None)), func.to_char(FOIRawRequest.created_at, 'YYYY-mm-DD HH:MM:SS')), ], else_ = FOIRawRequest.requestrawdata['receivedDateUF'].astext).label('receivedDateUF') @@ -612,7 +615,7 @@ def getbasequery(cls, additionalfilter=None, userid=None, isiaorestrictedfileman @classmethod def getrequestssubquery(cls, filterfields, keyword, additionalfilter, userid, isiaorestrictedfilemanager): basequery = FOIRawRequest.getbasequery(additionalfilter, userid, isiaorestrictedfilemanager) - basequery = basequery.filter(FOIRawRequest.status != 'Unopened').filter(FOIRawRequest.status != 'Closed') + basequery = basequery.filter(FOIRawRequest.status != StateName.unopened.value).filter(FOIRawRequest.status != StateName.closed.value) #filter/search if(len(filterfields) > 0 and keyword is not None): filtercondition = FOIRawRequest.getfilterforrequestssubquery(filterfields, keyword) @@ -775,7 +778,7 @@ def getfilterforadvancedsearch(cls, params): filtercondition.append(requeststatecondition['condition']) includeclosed = requeststatecondition['includeclosed'] else: - filtercondition.append(FOIRawRequest.status != 'Unopened') #not return Unopened by default + filtercondition.append(FOIRawRequest.status != StateName.unopened.value) #not return Unopened by default #request status: overdue, on time - no due date for unopen & intake in progress, so return all except closed if(len(params['requeststatus']) > 0 and includeclosed == False): @@ -783,7 +786,7 @@ def getfilterforadvancedsearch(cls, params): #no rawrequest returned for this case filtercondition.append(FOIRawRequest.status == 'ReturnNothing') else: - filtercondition.append(FOIRawRequest.status != 'Closed') + filtercondition.append(FOIRawRequest.status != StateName.closed.value) #request type: personal, general if(len(params['requesttype']) > 0): @@ -845,14 +848,14 @@ def getfilterforrequeststate(cls, params, includeclosed): requeststatecondition = [] for state in params['requeststate']: if(state == '3'): - requeststatecondition.append(FOIRawRequest.status == 'Closed') + requeststatecondition.append(FOIRawRequest.status == StateName.closed.value) includeclosed = True elif(state == '4'): - requeststatecondition.append(FOIRawRequest.status == 'Redirect') + requeststatecondition.append(FOIRawRequest.status == StateName.redirect.value) elif(state == '5'): - requeststatecondition.append(FOIRawRequest.status == 'Unopened') + requeststatecondition.append(FOIRawRequest.status == StateName.unopened.value) elif(state == '6'): - requeststatecondition.append(FOIRawRequest.status == 'Intake in Progress') + requeststatecondition.append(FOIRawRequest.status == StateName.intakeinprogress.value) if(len(requeststatecondition) == 0): requeststatecondition.append(FOIRawRequest.status == 'Not Applicable') #searched state does not apply to rawrequests @@ -1009,8 +1012,8 @@ def getlatestsection5pendings(cls): (SELECT DISTINCT ON (requestid) requestid, created_at, version, status, axisrequestid FROM public."FOIRawRequests" ORDER BY requestid ASC, version DESC) foireqs - WHERE foireqs.status = 'Section 5 Pending';""" - rs = db.session.execute(text(sql)) + WHERE foireqs.status = :requeststatus;""" + rs = db.session.execute(text(sql), {'requeststatus': StateName.section5pending.value}) for row in rs: section5pendings.append({"requestid": row["requestid"], "version": row["version"], "statusname": row["status"], "created_at": row["created_at"], "axisrequestid": ["axisrequestid"]}) except Exception as ex: @@ -1022,4 +1025,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', 'requeststatuslabel', '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 diff --git a/request-management-api/request_api/models/FOIRequestNotificationUsers.py b/request-management-api/request_api/models/FOIRequestNotificationUsers.py index e35dbda75..0e909cf21 100644 --- a/request-management-api/request_api/models/FOIRequestNotificationUsers.py +++ b/request-management-api/request_api/models/FOIRequestNotificationUsers.py @@ -212,7 +212,7 @@ def geteventsubquery(cls, groups, filterfields, keyword, additionalfilter, useri ).join( FOINotifications, and_(FOINotifications.axisnumber == FOIRequests.axisrequestid), - ).filter(FOIRequests.requeststatusid != 3) + ).filter(FOIRequests.requeststatuslabel != StateName.closed.name) if(additionalfilter == 'watchingRequests'): #watchby @@ -262,7 +262,7 @@ def getgroupfilters(cls, groups): FOIRequests.assignedgroup == group, and_( FOIRequests.assignedgroup == IAOTeamWithKeycloackGroup.flex.value, - FOIRequests.requeststatusid.in_([1]) + FOIRequests.requeststatuslabel.in_([StateName.open.name]) ) ) ) @@ -272,7 +272,7 @@ def getgroupfilters(cls, groups): FOIRequests.assignedgroup == group, and_( FOIRequests.assignedministrygroup == group, - FOIRequests.requeststatusid.in_([2,7,9,8,10,11,12,13,14,17,18]) + FOIRequests.requeststatuslabel.in_([StateName.callforrecords.name,StateName.recordsreview.name,StateName.feeestimate.name,StateName.consult.name,StateName.ministrysignoff.name,StateName.onhold.name,StateName.deduplication.name,StateName.harmsassessment.name,StateName.response.name,StateName.tagging.name,StateName.readytoscan.name]) ) ) ) diff --git a/request-management-api/request_api/models/FOIRequestStatus.py b/request-management-api/request_api/models/FOIRequestStatus.py index fa751e971..439c9f6ed 100644 --- a/request-management-api/request_api/models/FOIRequestStatus.py +++ b/request-management-api/request_api/models/FOIRequestStatus.py @@ -9,6 +9,7 @@ class FOIRequestStatus(db.Model): name = db.Column(db.String(100), unique=False, nullable=False) description = db.Column(db.String(255), unique=False, nullable=True) isactive = db.Column(db.Boolean, unique=False, nullable=False) + statuslabel = db.Column(db.String(50), unique=True, nullable=False) @classmethod def getrequeststatuses(cls): @@ -17,17 +18,17 @@ def getrequeststatuses(cls): return requeststatus_schema.dump(query) @classmethod - def getrequeststatusid(cls,status): + def getrequeststatus(cls,status): requeststatus_schema = RequestStatusSchema() query = db.session.query(FOIRequestStatus).filter_by(name=status).first() return requeststatus_schema.dump(query) @classmethod - def getrequeststatusname(cls,statusid): + def getrequeststatusbylabel(cls,statuslabel): requeststatus_schema = RequestStatusSchema() - query = db.session.query(FOIRequestStatus).filter_by(requeststatusid=statusid, isactive=True).first() + query = db.session.query(FOIRequestStatus).filter_by(statuslabel=statuslabel, isactive=True).first() return requeststatus_schema.dump(query) class RequestStatusSchema(ma.Schema): class Meta: - fields = ('requeststatusid', 'name', 'description','isactive') \ No newline at end of file + fields = ('requeststatusid', 'name', 'description','isactive','statuslabel') \ No newline at end of file diff --git a/request-management-api/request_api/models/FOIRequestTeams.py b/request-management-api/request_api/models/FOIRequestTeams.py index 02d02714b..e6ddbe50f 100644 --- a/request-management-api/request_api/models/FOIRequestTeams.py +++ b/request-management-api/request_api/models/FOIRequestTeams.py @@ -4,12 +4,15 @@ from sqlalchemy.sql.schema import ForeignKey from sqlalchemy import text import logging +from request_api.utils.enums import StateName + class FOIRequestTeam(db.Model): __tablename__ = 'FOIRequestTeams' # Defining the columns requestteamid = db.Column(db.Integer, primary_key=True,autoincrement=True) requesttype = db.Column(db.String(100), unique=False, nullable=True) requeststatusid = db.Column(db.Integer,ForeignKey('FOIRequestStatuses.requeststatusid')) + requeststatuslabel = db.Column(db.String(50), unique=False, nullable=False) teamid = db.Column(db.Integer,ForeignKey('OperatingTeams.teamid')) programareaid = db.Column(db.Integer,ForeignKey('ProgramAreas.programareaid')) isactive = db.Column(db.Boolean, unique=False, nullable=False) @@ -23,14 +26,15 @@ def getrequestteams(cls): @classmethod def getteamsbystatusandprogramarea(cls, requesttype, status, bcgovcode): teams = [] - try: + try: + # and replace(lower(fs2."name"),' ','') = :status sql = """ with mappedteams as ( select ot."name" as name, ot."type" as type, ft.requestteamid as orderby from "FOIRequestTeams" ft inner join "FOIRequestStatuses" fs2 on ft.requeststatusid = fs2.requeststatusid inner join "OperatingTeams" ot on ft.teamid = ot.teamid left join "ProgramAreas" pa on ft.programareaid = pa.programareaid - where ft.isactive = true and lower(ft.requesttype) = :requesttype - and replace(lower(fs2."name"),' ','') = :status + where ft.isactive = true and lower(ft.requesttype) = :requesttype + and ft.requeststatuslabel = :status and (lower(pa.bcgovcode) = :bcgovcode or ft.programareaid is null) ) -- remove the with statement and below query go back to mapped teams only in assignee drop down @@ -57,8 +61,8 @@ def getprocessingteamsbytype(cls, requesttype): inner join "ProgramAreas" pa on ft.programareaid = pa.programareaid where lower(ft.requesttype) = :requesttype and ft.programareaid is not null and ot."type" = 'iao' - and ft.requeststatusid = 8""" - rs = db.session.execute(text(sql), {'requesttype': requesttype}) + and ft.requeststatuslabel = :requeststatuslabel""" + rs = db.session.execute(text(sql), {'requesttype': requesttype, 'requeststatuslabel': StateName.feeestimate.name}) for row in rs: teams.append({"team":row["team"], "ministry":row["ministry"], "bcgovcode":row["bcgovcode"], "iaocode":row["iaocode"]}) except Exception as ex: @@ -91,4 +95,4 @@ def getdefaultprocessingteamforpersonal(cls, bcgovcode): class FOIRequestTeamSchema(ma.Schema): class Meta: - fields = ('requestteamid', 'requesttype', 'requeststatusid','teamid','programareaid','isactive') \ No newline at end of file + fields = ('requestteamid', 'requesttype', 'requeststatusid','teamid','programareaid','isactive', 'requeststatuslabel') \ No newline at end of file diff --git a/request-management-api/request_api/models/views/FOIRequests.py b/request-management-api/request_api/models/views/FOIRequests.py index b4a85ddc8..baa3395f3 100644 --- a/request-management-api/request_api/models/views/FOIRequests.py +++ b/request-management-api/request_api/models/views/FOIRequests.py @@ -20,4 +20,5 @@ class FOIRequests(db.Model): ministryassignedtoformatted = db.Column(db.String(500)) description = db.Column(db.Text) crtid = db.Column(db.Text) + requeststatuslabel = db.Column(db.String(50)) diff --git a/request-management-api/request_api/resources/foirequest.py b/request-management-api/request_api/resources/foirequest.py index 290cd2ccc..58cf30376 100644 --- a/request-management-api/request_api/resources/foirequest.py +++ b/request-management-api/request_api/resources/foirequest.py @@ -28,6 +28,7 @@ from request_api.services.eventservice import eventservice from request_api.schemas.foirequestwrapper import FOIRequestWrapperSchema, EditableFOIRequestWrapperSchema, FOIRequestMinistrySchema, FOIRequestStatusSchema from request_api.schemas.foiassignee import FOIRequestAssigneeSchema +from request_api.utils.enums import StateName from marshmallow import Schema, fields, validate, ValidationError from request_api.utils.enums import MinistryTeamWithKeycloackGroup import json @@ -99,7 +100,7 @@ def post(): assignedtofirstname = request_json["assignedToFirstName"] if request_json.get("assignedToFirstName") != None else None assignedtomiddlename = request_json["assignedToMiddleName"] if request_json.get("assignedToMiddleName") != None else None assignedtolastname = request_json["assignedToLastName"] if request_json.get("assignedToLastName") != None else None - rawresult = rawrequestservice().saverawrequestversion(request_json,request_json['id'],assignedgroup,assignedto,"Archived",AuthHelper.getuserid(), assignedtofirstname,assignedtomiddlename,assignedtolastname) + rawresult = rawrequestservice().saverawrequestversion(request_json,request_json['id'],assignedgroup,assignedto,"Archived",AuthHelper.getuserid(), assignedtofirstname,assignedtomiddlename,assignedtolastname,StateName.archived.name) diff --git a/request-management-api/request_api/resources/request.py b/request-management-api/request_api/resources/request.py index cfc9fc012..58768694a 100644 --- a/request-management-api/request_api/resources/request.py +++ b/request-management-api/request_api/resources/request.py @@ -25,6 +25,7 @@ from request_api.services.rawrequestservice import rawrequestservice from request_api.services.documentservice import documentservice from request_api.services.eventservice import eventservice +from request_api.utils.enums import StateName import json import asyncio from jose import jwt as josejwt @@ -92,12 +93,13 @@ def post(requestid=None, actiontype=None): assigneefirstname = requestdata['assigneefirstname'] assigneemiddlename = requestdata['assigneemiddlename'] assigneelastname = requestdata['assigneelastname'] + statuslabel = requestdata['requeststatuslabel'] if int(requestid) and str(requestid) != "-1" : status = rawrequestservice().getstatus(updaterequest) - if status not in ['Intake in Progress', 'Closed', 'Redirect', 'Peer Review', 'Section 5 Pending', 'App Fee Owing']: + if statuslabel not in [StateName.intakeinprogress.name, StateName.closed.name, StateName.redirect.name, StateName.peerreview.name, StateName.section5pending.name, StateName.appfeeowing.name]: raise ValueError('Invalid request state.') - result = rawrequestservice().saverawrequestversion(updaterequest,requestid,assigneegroup,assignee,status,AuthHelper.getuserid(),assigneefirstname,assigneemiddlename,assigneelastname, actiontype) + result = rawrequestservice().saverawrequestversion(updaterequest,requestid,assigneegroup,assignee,status,AuthHelper.getuserid(),assigneefirstname,assigneemiddlename,assigneelastname, statuslabel, actiontype) assignee = '' if(actiontype == 'assignee'): assignee = getassignee(assigneefirstname,assigneelastname,assigneegroup) @@ -128,7 +130,8 @@ def getparams(updaterequest): 'assignee': updaterequest["assignedTo"] if 'assignedTo' in updaterequest else None, 'assigneefirstname': updaterequest["assignedToFirstName"] if updaterequest.get("assignedToFirstName") != None else None, 'assigneemiddlename': updaterequest["assignedToMiddleName"] if updaterequest.get("assignedToMiddleName") != None else None, - 'assigneelastname': updaterequest["assignedToLastName"] if updaterequest.get("assignedToLastName") != None else None + 'assigneelastname': updaterequest["assignedToLastName"] if updaterequest.get("assignedToLastName") != None else None, + 'requeststatuslabel': updaterequest["requeststatuslabel"] if updaterequest.get("requeststatuslabel") != None else None } @cors_preflight('GET,OPTIONS') diff --git a/request-management-api/request_api/schemas/foirequestwrapper.py b/request-management-api/request_api/schemas/foirequestwrapper.py index efdb027ac..ce3ef32f6 100644 --- a/request-management-api/request_api/schemas/foirequestwrapper.py +++ b/request-management-api/request_api/schemas/foirequestwrapper.py @@ -105,6 +105,7 @@ class Meta: # pylint: disable=too-few-public-methods 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) requeststatusid = fields.Int(data_key="requeststatusid",allow_none=True) + requeststatuslabel = fields.Str(data_key="requeststatuslabel",allow_none=False) closedate = fields.Date(data_key="closedate", required=False,allow_none=True) closereasonid = fields.Int(data_key="closereasonid",allow_none=True) correctionalServiceNumber = fields.Str(data_key="correctionalServiceNumber",allow_none=True, validate=[validate.Length(max=50, error=MAX_EXCEPTION_MESSAGE)]) @@ -168,6 +169,7 @@ class Meta: # pylint: disable=too-few-public-methods assignedgroup = fields.Str(data_key="assignedGroup",allow_none=True, validate=[validate.Length(max=250, error=MAX_EXCEPTION_MESSAGE)]) assignedto = fields.Str(data_key="assignedTo",allow_none=True, validate=[validate.Length(max=120, error=MAX_EXCEPTION_MESSAGE)]) requeststatusid = fields.Int(data_key="requeststatusid",allow_none=True) + requeststatuslabel = fields.Str(data_key="requeststatuslabel",allow_none=False) divisions = fields.Nested(FOIMinistryRequestDivisionSchema, many=True,allow_none=True) documents = fields.Nested(FOIMinistryRequestDocumentSchema, many=True,allow_none=True) assignedToFirstName = fields.Str(data_key="assignedToFirstName",allow_none=True, validate=[validate.Length(max=50, error=MAX_EXCEPTION_MESSAGE)]) diff --git a/request-management-api/request_api/services/events/state.py b/request-management-api/request_api/services/events/state.py index f317f6e7c..72cdaa439 100644 --- a/request-management-api/request_api/services/events/state.py +++ b/request-management-api/request_api/services/events/state.py @@ -9,6 +9,7 @@ from request_api.models.FOIRequestStatus import FOIRequestStatus import json from request_api.models.default_method_result import DefaultMethodResult +from request_api.utils.enums import StateName class stateevent: """ FOI Event management service @@ -34,12 +35,12 @@ def __haschanged(self, requestid, requesttype): if len(states) == 2: newstate = states[0] oldstate = states[1] - if newstate != oldstate and newstate != 'Intake in Progress': + if newstate != oldstate and newstate != StateName.intakeinprogress.value: return newstate return None def __createcommentwrapper(self, requestid, state, requesttype, userid, username): - if state == 'Archived': + if state == StateName.archived.value: _openedministries = FOIMinistryRequest.getministriesopenedbyuid(requestid) for ministry in _openedministries: response=self.__createcomment(ministry["ministryrequestid"], state, 'ministryrequest', userid, username) @@ -58,16 +59,17 @@ def __createcomment(self, requestid, state, requesttype, userid, username): def __createnotification(self, requestid, state, requesttype, userid): _notificationtype = "State" - if state == 'Call For Records' and requesttype == "ministryrequest": + if state == StateName.callforrecords.value and requesttype == "ministryrequest": foirequest = notificationservice().getrequest(requestid, requesttype) _notificationtype = "Group Members" if foirequest['assignedministryperson'] is None else "State" notification = self.__preparenotification(state) - if state == "Response" and requesttype == "ministryrequest": + if state == StateName.response.value and requesttype == "ministryrequest": signgoffapproval = FOIMinistryRequest().getrequest(requestid)['ministrysignoffapproval'] - notification = notification + f". Approved by {signgoffapproval['approvername']}, {signgoffapproval['approvertitle']} on {signgoffapproval['approveddate']}" - if state == 'Closed' or state == 'Archived' : + if signgoffapproval: + notification = notification + f". Approved by {signgoffapproval['approvername']}, {signgoffapproval['approvertitle']} on {signgoffapproval['approveddate']}" + if state == StateName.closed.value or state == StateName.archived.value: notificationservice().dismissnotificationsbyrequestid(requestid, requesttype) - if state == 'Archived': + if state == StateName.archived.value: _openedministries = FOIMinistryRequest.getministriesopenedbyuid(requestid) for ministry in _openedministries: response = notificationservice().createnotification({"message" : notification}, ministry["ministryrequestid"], 'ministryrequest', "State", userid) @@ -88,7 +90,7 @@ def __preparenotification(self, state): return self.__notificationmessage(state) def __preparegroupmembernotification(self, state, requestid): - if state == 'Call For Records': + if state == StateName.callforrecords.value: return self.__notificationcfrmessage(requestid) return self.__groupmembernotificationmessage(state) @@ -101,13 +103,14 @@ def __preparecomment(self, requestid, state,requesttype, username): return comment def __formatstate(self, state): - return "Open" if state == "Archived" else state + return StateName.open.value if state == StateName.archived.value else state def __commentmessage(self, state, username, requesttype, requestid): comment = username+' changed the state of the request to '+self.__formatstate(state) - if state == "Response" and requesttype == "ministryrequest": + if state == StateName.response.value and requesttype == "ministryrequest": signgoffapproval = FOIMinistryRequest().getrequest(requestid)['ministrysignoffapproval'] - comment = comment + f". Approved by {signgoffapproval['approvername']}, {signgoffapproval['approvertitle']} on {signgoffapproval['approveddate']}" + if signgoffapproval: + comment = comment + f". Approved by {signgoffapproval['approvername']}, {signgoffapproval['approvertitle']} on {signgoffapproval['approveddate']}" return comment def __notificationmessage(self, state): @@ -119,7 +122,7 @@ def __notificationcfrmessage(self, requestid): def __createcfrentry(self, state, ministryrequestid, userid): cfrfee = cfrfeeservice().getcfrfee(ministryrequestid) - if (state == "Fee Estimate" and cfrfee['cfrfeestatusid'] in (None, '')): + if (state == StateName.feeestimate.value and cfrfee['cfrfeestatusid'] in (None, '')): return cfrfeeservice().sanctioncfrfee(ministryrequestid, {"status": "review"}, userid) else: return DefaultMethodResult(True,'No action needed',ministryrequestid) diff --git a/request-management-api/request_api/services/foirequest/requestservicebuilder.py b/request-management-api/request_api/services/foirequest/requestservicebuilder.py index 4f6db7aa5..d3f5a4d8b 100644 --- a/request-management-api/request_api/services/foirequest/requestservicebuilder.py +++ b/request-management-api/request_api/services/foirequest/requestservicebuilder.py @@ -8,8 +8,9 @@ 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.FOIRequestStatus import FOIRequestStatus from datetime import datetime as datetime2 -from request_api.utils.enums import MinistryTeamWithKeycloackGroup +from request_api.utils.enums import MinistryTeamWithKeycloackGroup, StateName from request_api.services.foirequest.requestserviceconfigurator import requestserviceconfigurator from request_api.services.foirequest.requestserviceministrybuilder import requestserviceministrybuilder @@ -22,7 +23,8 @@ class requestservicebuilder(requestserviceconfigurator): def createministry(self, requestschema, ministry, activeversion, userid, filenumber=None, ministryid=None): foiministryrequest = FOIMinistryRequest() foiministryrequest.__dict__.update(ministry) - foiministryrequest.requeststatusid = requestschema.get("requeststatusid") + foiministryrequest.requeststatusid = self.__getrequeststatusid(requestschema.get("requeststatuslabel")) + foiministryrequest.requeststatuslabel = requestschema.get("requeststatuslabel") foiministryrequest.isactive = True foiministryrequest.axisrequestid = requestschema.get("axisRequestId") foiministryrequest.axissyncdate = requestschema.get("axisSyncDate") @@ -43,9 +45,9 @@ def createministry(self, requestschema, ministry, activeversion, userid, filenum startdate = requestschema.get("requestProcessStart") foiministryrequest.startdate = startdate foiministryrequest.createdby = userid - requeststatusid = self.getpropertyvaluefromschema(requestschema, 'requeststatusid') - if requeststatusid is not None: - status = self.getstatusname(requeststatusid) + requeststatuslabel = self.getpropertyvaluefromschema(requestschema, 'requeststatuslabel') + if requeststatuslabel is not None: + status = self.getstatusname(requeststatuslabel) if self.isNotBlankorNone(requestschema,"fromDate","main") == True: foiministryrequest.recordsearchfromdate = requestschema.get("fromDate") if self.isNotBlankorNone(requestschema,"toDate","main") == True: @@ -89,7 +91,7 @@ def __updateassignedtoandgroup(self, foiministryrequest, requestschema, ministry foiministryrequest.assignedto = None def __isgrouprequired(self,status): - if status == "Call For Records" or status == "Review" or status == "Consult" or status == "Fee Assessed" or status == "Ministry Sign Off" or status == "Response": + if status == StateName.callforrecords.value or status == StateName.recordsreview.value or status == StateName.consult.value or status == StateName.feeestimate.value or status == StateName.ministrysignoff.value or status == StateName.response.value: return True else: return False @@ -97,6 +99,17 @@ def __isgrouprequired(self,status): def __getgroupname(self, requesttype, bcgovcode): return 'Flex Team' if requesttype == "general" else FOIRequestTeam.getdefaultprocessingteamforpersonal(bcgovcode) + def __getrequeststatusid(self, requeststatuslabel): + state = FOIRequestStatus.getrequeststatusbylabel( + requeststatuslabel + ) + stateid = ( + state.get("requeststatusid") + if isinstance(state, dict) and state.get("requeststatusid") not in (None, "") + else "" + ) + return stateid + def createcontactinformation(self,dataformat, name, value, contacttypes, userid): contactinformation = FOIRequestContactInformation() contactinformation.contactinformation = value diff --git a/request-management-api/request_api/services/foirequest/requestserviceconfigurator.py b/request-management-api/request_api/services/foirequest/requestserviceconfigurator.py index a2a87909f..2c31f1674 100644 --- a/request-management-api/request_api/services/foirequest/requestserviceconfigurator.py +++ b/request-management-api/request_api/services/foirequest/requestserviceconfigurator.py @@ -15,10 +15,10 @@ class requestserviceconfigurator: """This class consolidates helper fiunctions and constants """ - def getstatusname(self,requeststatusid): + def getstatusname(self,requeststatuslabel): allstatus = FOIRequestStatus().getrequeststatuses() for status in allstatus: - if status["requeststatusid"] == requeststatusid: + if status["statuslabel"] == requeststatuslabel: return status["name"] return None; diff --git a/request-management-api/request_api/services/foirequest/requestservicecreate.py b/request-management-api/request_api/services/foirequest/requestservicecreate.py index 6d4b2142f..ac6f24275 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.utils.enums import StateName import json class requestservicecreate: @@ -169,10 +170,10 @@ def __prepareapplicants(self, foirequestschema, userid): return requestapplicantarr def __disablewatchers(self, ministryid, requestschema, userid): - requeststatusid = requestschema.get("requeststatusid") if 'requeststatusid' in requestschema else None - if requeststatusid is not None: - status = requestserviceconfigurator().getstatusname(requeststatusid) - if status == "Open": + requeststatuslabel = requestschema.get("requeststatuslabel") if 'requeststatuslabel' in requestschema else None + if requeststatuslabel is not None: + status = requestserviceconfigurator().getstatusname(requeststatuslabel) + if status == StateName.open.value: watchers = watcherservice().getministryrequestwatchers(int(ministryid), True) for watcher in watchers: watcherschema = {"ministryrequestid":ministryid,"watchedbygroup":watcher["watchedbygroup"],"watchedby":watcher["watchedby"],"isactive":False} diff --git a/request-management-api/request_api/services/foirequest/requestservicegetter.py b/request-management-api/request_api/services/foirequest/requestservicegetter.py index e5ae2c249..f8a7492c4 100644 --- a/request-management-api/request_api/services/foirequest/requestservicegetter.py +++ b/request-management-api/request_api/services/foirequest/requestservicegetter.py @@ -15,6 +15,7 @@ from request_api.services.programareaservice import programareaservice from request_api.utils.commons.datetimehandler import datetimehandler from request_api.services.external.keycloakadminservice import KeycloakAdminService +from request_api.utils.enums import StateName class requestservicegetter: """ This class consolidates retrival of FOI request for actors: iao and ministry. @@ -29,7 +30,7 @@ def getrequest(self,foirequestid,foiministryrequestid): iaorestrictrequestdetails = FOIRestrictedMinistryRequest.getrestricteddetails(ministryrequestid=foiministryrequestid,type='iao') baserequestinfo = self.__preparebaseinfo(request,foiministryrequestid,requestministry,requestministrydivisions) - baserequestinfo['lastStatusUpdateDate'] = FOIMinistryRequest.getLastStatusUpdateDate(foiministryrequestid, requestministry['requeststatus.requeststatusid']).strftime(self.__genericdateformat()), + baserequestinfo['lastStatusUpdateDate'] = FOIMinistryRequest.getLastStatusUpdateDate(foiministryrequestid, requestministry['requeststatuslabel']).strftime(self.__genericdateformat()), for contactinfo in requestcontactinformation: if contactinfo['contacttype.name'] == 'Email': baserequestinfo.update({'email':contactinfo['contactinformation']}) @@ -152,8 +153,8 @@ def __preparebaseinfo(self,request,foiministryrequestid,requestministry,requestm 'description': requestministry['description'], 'fromDate': parse(requestministry['recordsearchfromdate']).strftime(self.__genericdateformat()) if requestministry['recordsearchfromdate'] is not None else '', 'toDate': parse(requestministry['recordsearchtodate']).strftime(self.__genericdateformat()) if requestministry['recordsearchtodate'] is not None else '', - 'currentState':requestministry['requeststatus.name'], - 'requeststatusid':requestministry['requeststatus.requeststatusid'], + 'currentState':requestministry['requeststatus.name'], + 'requeststatuslabel':requestministry['requeststatuslabel'], 'requestProcessStart': parse(requestministry['startdate']).strftime(self.__genericdateformat()) if requestministry['startdate'] is not None else '', 'dueDate':parse(requestministry['duedate']).strftime(self.__genericdateformat()), 'originalDueDate': parse(requestministry['originalldd']).strftime(self.__genericdateformat()) if requestministry['originalldd'] is not None else parse(requestministry['duedate']).strftime(self.__genericdateformat()), @@ -213,7 +214,7 @@ def getonholdtransition(self, foiministryrequestid): onholddate = None transitions = FOIMinistryRequest.getrequeststatusById(foiministryrequestid) for entry in transitions: - if entry['requeststatusid'] == 11: + if entry['requeststatuslabel'] == StateName.onhold.name: onholddate = datetimehandler().convert_to_pst(entry['created_at'],'%Y-%m-%d') else: if onholddate is not 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..56db80d2d 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.FOIRequestStatus import FOIRequestStatus from request_api.services.foirequest.requestserviceconfigurator import requestserviceconfigurator from datetime import datetime as datetime2 @@ -76,7 +77,8 @@ def createfoiministryrequestfromobject(self, ministryschema, requestschema, user foiministryrequest.assignedto = None if usertype == "iao" and 'assignedto' in requestschema and requestschema['assignedto'] in (None, '') else ministryschema["assignedto"] foiministryrequest.ministrysignoffapproval = requestdict["ministrysignoffapproval"] - foiministryrequest.requeststatusid = requestdict['requeststatusid'] + foiministryrequest.requeststatusid = self.__getrequeststatusid(requestdict['requeststatuslabel']) + foiministryrequest.requeststatuslabel = requestdict['requeststatuslabel'] foiministryrequest.programareaid = requestdict['programareaid'] foiministryrequest.createdby = userid @@ -88,6 +90,16 @@ def createfoiministryrequestfromobject(self, ministryschema, requestschema, user foiministryrequest.closereasonid = requestdict['closereasonid'] return foiministryrequest + def __getrequeststatusid(self, requeststatuslabel): + state = FOIRequestStatus.getrequeststatusbylabel( + requeststatuslabel + ) + stateid = ( + state.get("requeststatusid") + if isinstance(state, dict) and state.get("requeststatusid") not in (None, "") + else "" + ) + return stateid def __createministrydivisions(self, requestschema, foiministryrequestid, foiministryrequestversion, userid): if 'divisions' in requestschema: return self.createfoirequestdivision(requestschema,foiministryrequestid ,foiministryrequestversion + 1, userid) @@ -111,7 +123,7 @@ def createfoiministryrequestfromobject1(self, ministryschema, requestschema): 'duedate': requestschema['duedate'] if 'duedate' in requestschema else ministryschema["duedate"], #and isextension':= True 'assignedministrygroup': requestschema['assignedministrygroup'] if 'assignedministrygroup' in requestschema else ministryschema["assignedministrygroup"], 'assignedgroup': requestschema['assignedgroup'] if 'assignedgroup' in requestschema else ministryschema["assignedgroup"], - 'requeststatusid': requestschema['requeststatusid'] if 'requeststatusid' in requestschema else ministryschema["requeststatus.requeststatusid"], + 'requeststatuslabel': requestschema['requeststatuslabel'] if 'requeststatuslabel' in requestschema else ministryschema["requeststatuslabel"], 'programareaid': ministryschema["programarea.programareaid"] if 'programarea.programareaid' in ministryschema else None, 'closedate': requestschema['closedate'] if 'closedate' in requestschema else None, 'closereasonid': requestschema['closereasonid'] if 'closereasonid' in requestschema else None, diff --git a/request-management-api/request_api/services/foirequest/requestserviceupdate.py b/request-management-api/request_api/services/foirequest/requestserviceupdate.py index c800ae387..a85ca38e9 100644 --- a/request-management-api/request_api/services/foirequest/requestserviceupdate.py +++ b/request-management-api/request_api/services/foirequest/requestserviceupdate.py @@ -19,7 +19,7 @@ def updaterequest(self,foirequestschema,foirequestid,userid): for ministry in foirequestschema.get("selectedMinistries"): for status in allstatus: if ministry["status"] == status["name"]: - updatedministries.append({"filenumber" : ministry["filenumber"], "requeststatusid": status["requeststatusid"]}) + updatedministries.append({"filenumber" : ministry["filenumber"], "requeststatuslabel": status["statuslabel"]}) return FOIRequest.updateStatus(foirequestid, updatedministries, userid) def updateministryrequestduedate(self, ministryrequestid, duedate, userid): diff --git a/request-management-api/request_api/services/rawrequest/rawrequestservicegetter.py b/request-management-api/request_api/services/rawrequest/rawrequestservicegetter.py index bb56f9317..b8b1cf870 100644 --- a/request-management-api/request_api/services/rawrequest/rawrequestservicegetter.py +++ b/request-management-api/request_api/services/rawrequest/rawrequestservicegetter.py @@ -7,6 +7,7 @@ from dateutil.parser import parse import maya from request_api.models.FOIAssignees import FOIAssignee +from request_api.utils.enums import StateName class rawrequestservicegetter: """ This class consolidates retrival of FOI raw request for actors: iao. @@ -52,7 +53,7 @@ def getallrawrequests(self): def getrawrequestforid(self, requestid): request = FOIRawRequest.get_request(requestid) request = self.__attachministriesinfo(request) - if request != {} and (request['version'] == 1 or request['status'] == 'Unopened') and request['sourceofsubmission'] != "intake": + if request != {} and (request['version'] == 1 or request['status'] == StateName.unopened.value) and request['sourceofsubmission'] != "intake": requestrawdata = request['requestrawdata'] requesttype = requestrawdata['requestType']['requestType'] baserequestinfo = self.__preparebaserequestinfo(requestid, request, requesttype, requestrawdata) @@ -60,16 +61,15 @@ def getrawrequestforid(self, requestid): baserequestinfo['additionalPersonalInfo'] = self.__prepareadditionalpersonalinfo(requestrawdata) return baserequestinfo elif request != {} and request['version'] != 1 and request['sourceofsubmission'] != "intake": - request['requestrawdata']['currentState'] = request['status'] - requeststatus = FOIRequestStatus().getrequeststatusid(request['status']) - request['requestrawdata']['requeststatusid'] = requeststatus['requeststatusid'] + request['requestrawdata']['currentState'] = request['status'] + request['requestrawdata']['requeststatuslabel'] = request['requeststatuslabel'] request['requestrawdata']['lastStatusUpdateDate'] = FOIRawRequest.getLastStatusUpdateDate(requestid, request['status']).strftime(self.__generaldateformat()) - if request['status'] == 'Closed': + if request['requeststatuslabel'] == StateName.closed.name: request['requestrawdata']['stateTransition']= FOIRawRequest.getstatesummary(requestid) request['requestrawdata']['wfinstanceid'] = request['wfinstanceid'] request['requestrawdata']['closedate']= self.__getclosedate(request['closedate']) request['requestrawdata']['isiaorestricted']= request['isiaorestricted'] if request['isiaorestricted'] is not None else False - return request['requestrawdata'] + return request['requestrawdata'] elif request != {} and request['sourceofsubmission'] == "intake": requestrawdata = request['requestrawdata'] requesttype = requestrawdata['requestType'] @@ -81,8 +81,8 @@ def getrawrequestforid(self, requestid): request['requestrawdata']['wfinstanceid'] = request['wfinstanceid'] request['requestrawdata']['currentState'] = request['status'] - requeststatus = FOIRequestStatus().getrequeststatusid(request['status']) - request['requestrawdata']['requeststatusid'] = requeststatus['requeststatusid'] + requeststatus = FOIRequestStatus().getrequeststatus(request['status']) + request['requestrawdata']['requeststatuslabel'] = requeststatus['statuslabel'] request['requestrawdata']['lastStatusUpdateDate'] = FOIRawRequest.getLastStatusUpdateDate(requestid, request['status']).strftime(self.__generaldateformat()) request['requestrawdata']['stateTransition']= FOIRawRequest.getstatesummary(requestid) request['requestrawdata']['closedate']= self.__getclosedate(request['closedate']) diff --git a/request-management-api/request_api/services/rawrequestservice.py b/request-management-api/request_api/services/rawrequestservice.py index 6abaf1ff1..1c0564733 100644 --- a/request-management-api/request_api/services/rawrequestservice.py +++ b/request-management-api/request_api/services/rawrequestservice.py @@ -15,7 +15,8 @@ from request_api.exceptions import BusinessException, Error from request_api.models.default_method_result import DefaultMethodResult from request_api.models.FOIRawRequestWatchers import FOIRawRequestWatcher -from request_api.services.foirequest.requestserviceconfigurator import requestserviceconfigurator +from request_api.services.foirequest.requestserviceconfigurator import requestserviceconfigurator +from request_api.utils.enums import StateName import logging class rawrequestservice: @@ -91,13 +92,13 @@ def doesrequirepayment(requestdatajson): return requestdatajson['requiresPayment'] raise BusinessException(Error.DATA_NOT_FOUND) - def saverawrequestversion(self, _requestdatajson, _requestid, _assigneegroup, _assignee, status, userid, assigneefirstname, assigneemiddlename, assigneelastname, actiontype=None): + def saverawrequestversion(self, _requestdatajson, _requestid, _assigneegroup, _assignee, status, userid, assigneefirstname, assigneemiddlename, assigneelastname, statuslabel, actiontype=None): ispiiredacted = _requestdatajson["ispiiredacted"] if 'ispiiredacted' in _requestdatajson else False #Get documents if actiontype == "assignee": result = FOIRawRequest.saverawrequestassigneeversion(_requestid, _assigneegroup, _assignee, userid, assigneefirstname, assigneemiddlename, assigneelastname) else: - result = FOIRawRequest.saverawrequestversion(_requestdatajson, _requestid, _assigneegroup, _assignee, status,ispiiredacted, userid, assigneefirstname, assigneemiddlename, assigneelastname) + result = FOIRawRequest.saverawrequestversion(_requestdatajson, _requestid, _assigneegroup, _assignee, status,ispiiredacted, userid, statuslabel, assigneefirstname, assigneemiddlename, assigneelastname) documentservice().createrawrequestdocumentversion(_requestid) return result @@ -125,10 +126,10 @@ def getrawrequestfields(self, requestid, fields): return rawrequestservicegetter().getrawrequestfieldsforid(requestid, fields) def getstatus(self, foirequest): - statusid = foirequest["requeststatusid"] if "requeststatusid" in foirequest else None - if statusid is not None: + statuslabel = foirequest["requeststatuslabel"] if "requeststatuslabel" in foirequest else None + if statuslabel is not None: try: - return requestserviceconfigurator().getstatusname(statusid) + return requestserviceconfigurator().getstatusname(statuslabel) # if statusid== 4: # return 'Redirect' # if statusid == 3: @@ -137,7 +138,7 @@ def getstatus(self, foirequest): # return 'Peer Review' except KeyError: print("Key Error on requeststatusid, ignore will be intake in Progress") - return 'Intake in Progress' + return StateName.intakeinprogress.value def getaxisequestids(self): return rawrequestservicegetter().getaxisequestids() diff --git a/request-management-api/request_api/services/requestservice.py b/request-management-api/request_api/services/requestservice.py index d98d24cb3..445ec9914 100644 --- a/request-management-api/request_api/services/requestservice.py +++ b/request-management-api/request_api/services/requestservice.py @@ -62,8 +62,8 @@ def saverequest( ) def saverequestversion(self, foirequestschema, foirequestid, ministryid, userid): - nextstate = FOIRequestStatus.getrequeststatusname( - foirequestschema["requeststatusid"] + nextstate = FOIRequestStatus.getrequeststatusbylabel( + foirequestschema["requeststatuslabel"] ) nextstatename = ( nextstate.get("name") @@ -112,8 +112,8 @@ def postpaymentstatetransition( foirequest = self.updateduedate( requestid, ministryrequestid, paymentdate, _foirequest, nextstatename ) - status = FOIRequestStatus().getrequeststatusid(nextstatename) - foirequest["requeststatusid"] = status["requeststatusid"] + status = FOIRequestStatus().getrequeststatus(nextstatename) + foirequest["requeststatuslabel"] = status["statuslabel"] return requestservicecreate().saverequestversion( foirequest, requestid, ministryrequestid, "Online Payment" ) @@ -204,7 +204,7 @@ def copysubjectcode(self, subjectcode, ministries, userid): def postopeneventtoworkflow(self, id, requestschema, ministries): pid = workflowservice().syncwfinstance("rawrequest", requestschema["id"]) - workflowservice().postunopenedevent(id, pid, requestschema, "Open", ministries) + workflowservice().postunopenedevent(id, pid, requestschema, StateName.open.value, ministries) def postfeeeventtoworkflow( self, requestid, ministryrequestid, paymentstatus, nextstatename=None @@ -215,14 +215,14 @@ def postfeeeventtoworkflow( ) def posteventtoworkflow(self, id, requestschema, data, usertype): - requeststatusid = ( - requestschema.get("requeststatusid") - if "requeststatusid" in requestschema + requeststatuslabel = ( + requestschema.get("requeststatuslabel") + if "requeststatuslabel" in requestschema else None ) status = ( - requestserviceconfigurator().getstatusname(requeststatusid) - if requeststatusid is not None + requestserviceconfigurator().getstatusname(requeststatuslabel) + if requeststatuslabel is not None else None ) pid = workflowservice().syncwfinstance("ministryrequest", id) diff --git a/request-management-api/request_api/services/workflowservice.py b/request-management-api/request_api/services/workflowservice.py index f4b6f81a0..1cbcbb1db 100644 --- a/request-management-api/request_api/services/workflowservice.py +++ b/request-management-api/request_api/services/workflowservice.py @@ -70,7 +70,7 @@ def postopenedevent(self, id, wfinstanceid, requestsschema, data, newstatus, use _variables = bpmservice().getinstancevariables(wfinstanceid) if ministry["status"] == OpenedEvent.callforrecords.value and (("status" not in _variables) or (_variables not in (None, []) and "status" in _variables and _variables["status"]["value"] != OpenedEvent.callforrecords.value)): messagename = MessageType.iaoopencomplete.value - elif _variables not in (None, []) and ("status" in _variables and _variables["status"]["value"] == "Closed"): + elif _variables not in (None, []) and ("status" in _variables and _variables["status"]["value"] == StateName.closed.value): return bpmservice().reopenevent(wfinstanceid, metadata, MessageType.iaoreopen.value) else: return bpmservice().openedcomplete(wfinstanceid, filenumber, metadata, messagename) diff --git a/request-management-api/request_api/utils/enums.py b/request-management-api/request_api/utils/enums.py index f21d807ab..becdb9d9e 100644 --- a/request-management-api/request_api/utils/enums.py +++ b/request-management-api/request_api/utils/enums.py @@ -149,15 +149,20 @@ class StateName(Enum): redirect = "Redirect" unopened = "Unopened" intakeinprogress = "Intake in Progress" - recordsreview = "Records Review" - feeestimate = "Fee Estimate" consult = "Consult" ministrysignoff = "Ministry Sign Off" onhold = "On Hold" deduplication = "Deduplication" harmsassessment = "Harms Assessment" response = "Response" - + feeestimate = "Fee Estimate" + recordsreview = "Records Review" + archived = "Archived" + peerreview = "Peer Review" + tagging = "Tagging" + readytoscan = "Ready to Scan" + appfeeowing = "App Fee Owing" + section5pending = "Section 5 Pending" class CacheUrls(Enum): keycloakusers= "/api/foiassignees" programareas= "/api/foiflow/programareas" From 9ff9448b6796079e2cd01cf6d393c3e220deedb1 Mon Sep 17 00:00:00 2001 From: Abin Antony Date: Thu, 30 Nov 2023 14:43:14 -0800 Subject: [PATCH 04/22] #4711 ETL packages for assignees, Team updtes --- .../ApplicantRequestMappings.dtsx | 38 +-- .../FOIApplicants.dtsx | 18 +- .../FOIMOD.CFD.ETL.DataMigration.dtproj | 76 ++++- .../FOIMOD.CFD.ETL.DataMigration.dtproj.user | 2 + .../FOIMinistryRequests.dtsx | 116 ++++++-- .../FOIRequestContactInformation.dtsx | 106 +++---- .../FOIRequests.dtsx | 14 +- .../IXIAS_CIRMOTST , 1435.ATIPITEST.conmgr | 2 +- .../Project.params | 98 ++++++- .../UpdateRequestassignment.dtsx | 213 ++++++++++++++ .../UpdateTeamtoChildAndEducation.dtsx | 67 +++++ .../migrateassignees.dtsx | 263 ++++++++++++++++++ 12 files changed, 876 insertions(+), 137 deletions(-) create mode 100644 datamigrations/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration/UpdateRequestassignment.dtsx create mode 100644 datamigrations/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration/UpdateTeamtoChildAndEducation.dtsx create mode 100644 datamigrations/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration/migrateassignees.dtsx diff --git a/datamigrations/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration/ApplicantRequestMappings.dtsx b/datamigrations/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration/ApplicantRequestMappings.dtsx index 9f0a03d27..6a03e1511 100644 --- a/datamigrations/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration/ApplicantRequestMappings.dtsx +++ b/datamigrations/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration/ApplicantRequestMappings.dtsx @@ -11,8 +11,8 @@ DTS:LocaleID="1033" DTS:ObjectName="ApplicantRequestMappings" DTS:PackageType="5" - DTS:VersionBuild="64" - DTS:VersionGUID="{E74162C7-CB89-4371-98DA-C1E08F361BDA}"> + DTS:VersionBuild="65" + DTS:VersionGUID="{9F68B623-DB01-4BE6-99AD-D0EF1C647FB7}"> 8 @@ -62,7 +62,7 @@ + DTS:ThreadHint="0"> + DTS:ThreadHint="2"> + DTS:ThreadHint="0"> + DTS:ThreadHint="0"> + DTS:ThreadHint="1"> + DTS:VersionBuild="12" + DTS:VersionGUID="{57B2A59C-BDE3-4612-A3C1-13569FD94C0F}"> 8 @@ -25,7 +25,7 @@ DTS:Namespace="User" DTS:ObjectName="applicantqueryparam"> SELECT firstname,lastname,middleName,requesterid,CONVERT(varchar(MAX),'01-01-1900',120) as birthDate,businessName, GETDATE() as createdAt, 'cfdmigration' as createdBy,STRING_AGG(CAST(requestid as nvarchar(max)),', ') as requests ,MainApplicant FROM ( SELECT requesters.vcEmailID as email, requesters.iRequesterID as requesterid, requesters.vcFirstName as firstName, requesters.vcLastName as lastName, requesters.vcMiddleName as middleName, requestorfields.CUSTOMFIELD35 as birthDate, requesters.vcCompany as businessName, requests.vcVisibleRequestID as requestid, 1 as MainApplicant FROM tblRequests requests WITH (NOLOCK) LEFT OUTER JOIN EC_OFFICE office WITH (NOLOCK) ON requests.tiOfficeID = office.OFFICE_ID LEFT OUTER JOIN tblRequesters requesters WITH (NOLOCK) ON requests.iRequesterID = requesters.iRequesterID LEFT OUTER JOIN dbo.TBLREQUESTERCUSTOMFIELDS requestorfields WITH (NOLOCK) ON requesters.iRequesterID = requestorfields.IREQUESTERID WHERE office.OFFICE_CODE = 'CFD' AND requests.vcRequestStatus NOT IN ('Closed') AND requests.vcVisibleRequestID IN ('CFD-2021-12651','CFD-2023-30193') UNION ALL SELECT onbehalf.vcEmailID as email, onbehalf.iRequesterID as requesterid, onbehalf.vcFirstName as firstName, onbehalf.vcLastName as lastName, onbehalf.vcMiddleName as middleName, requestorfields.CUSTOMFIELD35 as birthDate, onbehalf.vcCompany as businessName, requests.vcVisibleRequestID as requestid, 0 as MainApplicant FROM tblRequests requests WITH (NOLOCK) LEFT OUTER JOIN EC_OFFICE office WITH (NOLOCK) ON requests.tiOfficeID = office.OFFICE_ID LEFT OUTER JOIN tblRequesters onbehalf WITH (NOLOCK) ON requests.iOnBehalfOf = onbehalf.iRequesterID LEFT OUTER JOIN dbo.TBLREQUESTERCUSTOMFIELDS requestorfields WITH (NOLOCK) ON onbehalf.iRequesterID = requestorfields.IREQUESTERID WHERE office.OFFICE_CODE = 'CFD' AND requests.vcRequestStatus NOT IN ('Closed') AND requests.vcVisibleRequestID IN ('CFD-2021-12651','CFD-2023-30193') and onbehalf.vcFirstName is NOT NULL ) AS T GROUP BY T.email,T.requesterid,T.firstname,T.lastname,T.middleName,T.requesterid,T.birthDate,T.businessName,T.MainApplicant ORDER BY T.firstname ASC + DTS:DataType="8">SELECT firstname, lastname, middleName, requesterid, CONVERT(varchar(MAX),birthDate,120) as birthDate, businessName, GETDATE() as createdAt, 'cfdmigration' as createdBy, STRING_AGG(CAST(requestid as nvarchar(max)),', ') as requests , MainApplicant FROM ( SELECT requesters.vcEmailID as email, requesters.iRequesterID as requesterid, requesters.vcFirstName as firstName, requesters.vcLastName as lastName, requesters.vcMiddleName as middleName, requestorfields.CUSTOMFIELD35 as birthDate, requesters.vcCompany as businessName, requests.vcVisibleRequestID as requestid, 1 as MainApplicant FROM tblRequests requests WITH (NOLOCK) LEFT OUTER JOIN EC_OFFICE office WITH (NOLOCK) ON requests.tiOfficeID = office.OFFICE_ID LEFT OUTER JOIN tblRequesters requesters WITH (NOLOCK) ON requests.iRequesterID = requesters.iRequesterID LEFT OUTER JOIN dbo.TBLREQUESTERCUSTOMFIELDS requestorfields WITH (NOLOCK) ON requesters.iRequesterID = requestorfields.IREQUESTERID WHERE office.OFFICE_CODE = 'CFD' AND requests.vcRequestStatus NOT IN ('Closed') AND requests.vcVisibleRequestID IN ('CFD-2021-12651','CFD-2023-30193') UNION ALL SELECT onbehalf.vcEmailID as email, onbehalf.iRequesterID as requesterid, onbehalf.vcFirstName as firstName, onbehalf.vcLastName as lastName, onbehalf.vcMiddleName as middleName, requestorfields.CUSTOMFIELD35 as birthDate, onbehalf.vcCompany as businessName, requests.vcVisibleRequestID as requestid, 0 as MainApplicant FROM tblRequests requests WITH (NOLOCK) LEFT OUTER JOIN EC_OFFICE office WITH (NOLOCK) ON requests.tiOfficeID = office.OFFICE_ID LEFT OUTER JOIN tblRequesters onbehalf WITH (NOLOCK) ON requests.iOnBehalfOf = onbehalf.iRequesterID LEFT OUTER JOIN dbo.TBLREQUESTERCUSTOMFIELDS requestorfields WITH (NOLOCK) ON onbehalf.iRequesterID = requestorfields.IREQUESTERID WHERE office.OFFICE_CODE = 'CFD' AND requests.vcRequestStatus NOT IN ('Closed') AND requests.vcVisibleRequestID IN ('CFD-2021-12651','CFD-2023-30193') and onbehalf.vcFirstName is NOT NULL ) AS T GROUP BY T.email,T.requesterid,T.firstname,T.lastname,T.middleName,T.requesterid,T.birthDate,T.businessName,T.MainApplicant ORDER BY T.firstname ASC @@ -591,7 +591,7 @@ @@ -603,13 +603,13 @@ - + diff --git a/datamigrations/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration.dtproj b/datamigrations/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration.dtproj index b1b17101b..bd221071c 100644 --- a/datamigrations/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration.dtproj +++ b/datamigrations/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration.dtproj @@ -26,7 +26,7 @@ WALTZ - AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAAxNy8IYXQUikuyRHfwqVBQAAAAACAAAAAAADZgAAwAAAABAAAAA0WsvjZzR76ItQUOsvjFPxAAAAAASAAACgAAAAEAAAAB6WqM0e3bF/ytcNb+00Vj+IAAAAbsMnsLvWvIvySgXvXtMoEl3R8G67DLCHIBL3kR/GH2MUqZpdgHf+GA623nwneseHO7/k1WEwNtQKoj3RJSAzVR2kKCBf/WuRo7OE7YHbUgHk4tAJ5+pg9H5AVaFycQMdmyhXf3aH5TbvKirS4dBijjsR1DVko71vw8v5SeKsbxBGdvk7myw8hBQAAABx9sgy9GQ3TLvYi2NH3xvLCs5wfg== + AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAap7i9B0arkWSE2oL+CF2DAAAAAACAAAAAAADZgAAwAAAABAAAAD+yB8O7hQw06vSOg9B6nN2AAAAAASAAACgAAAAEAAAAM4jfjU/hDOkCC1ezXIF1MiIAAAAmzelYxbiV+01rQA3S9sU1+4Fx0qODz8klPX80VJGWAV6D18pjC9YKo3Dw7k/Hejm87Lc2y6Ubgf/RrdiL6n4aw9YLaIlsn48ci5EmfvbouQQ5pO4zmpsyL4T2ktRnTJYsUmdgbv/y4LQk9nH0eVpKegmeoN3KKYhO3NHlc6YddYkaPMrf/5A0RQAAADYHmvdqqqK3sxsEtm3IrZpCQiNLA== 1 @@ -37,6 +37,9 @@ + + + @@ -301,10 +304,10 @@ FOIRequests 1 0 - 36 + 37 - {2215EF75-9178-4019-A65C-548BCB848EB3} + {9927CBA3-B5E5-4FA2-809A-E9EEBE87B69E} 8 @@ -318,10 +321,10 @@ Package1 1 0 - 49 + 68 - {959785B0-CF2F-46BD-B18F-F60A275D3B69} + {5D1A1911-0EC9-43B0-B177-A2AB5550A27B} 8 @@ -352,10 +355,10 @@ FOIRequestContactInformation 1 0 - 71 + 79 - {D8F0E47C-87C0-4352-B380-D36429864036} + {963DE22B-D953-4B51-A23F-11B823D5F17A} 8 @@ -369,10 +372,10 @@ FOIApplicants 1 0 - 8 + 12 - {47713682-1301-458C-9DB7-6F85D70A1E2F} + {57B2A59C-BDE3-4612-A3C1-13569FD94C0F} 8 @@ -403,10 +406,61 @@ FOIMinistryRequestSubjectCodes 1 0 - 15 + 27 + + + {F1AE1F1E-FC56-4C52-9E85-4390FC2E580B} + 8 + + + 1 + + + + + + {6951F32E-9E7C-4CBE-996D-B9EF1A7CDA68} + Package1 + 1 + 0 + 8 + + + {8687C0CE-4320-4480-AED1-13D717D04E74} + 8 + + + 1 + + + + + + {05F30183-3CEF-4CB7-B67C-063703B35BCD} + Package1 + 1 + 0 + 14 + + + {A3FB2639-F646-4BB0-9A51-D430E40D57CD} + 8 + + + 1 + + + + + + {790F7438-3BBE-4AAB-80F8-F171099BF968} + Package1 + 1 + 0 + 3 - {FECD18DF-8B81-43E0-812E-6647F05F22D6} + {CD3FF5AA-7DE9-491B-8CFD-7718F0113634} 8 diff --git a/datamigrations/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration.dtproj.user b/datamigrations/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration.dtproj.user index fb5695dc9..43de99a88 100644 --- a/datamigrations/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration.dtproj.user +++ b/datamigrations/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration.dtproj.user @@ -8,6 +8,8 @@ false + Tikal.DMZ + /SSISDB/CFDMigration/FOIMOD.CFD.ETL.DataMigration false diff --git a/datamigrations/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration/FOIMinistryRequests.dtsx b/datamigrations/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration/FOIMinistryRequests.dtsx index 6c371fb3b..d6990111c 100644 --- a/datamigrations/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration/FOIMinistryRequests.dtsx +++ b/datamigrations/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration/FOIMinistryRequests.dtsx @@ -11,8 +11,8 @@ DTS:LocaleID="1033" DTS:ObjectName="Package1" DTS:PackageType="5" - DTS:VersionBuild="49" - DTS:VersionGUID="{959785B0-CF2F-46BD-B18F-F60A275D3B69}"> + DTS:VersionBuild="72" + DTS:VersionGUID="{A1BD12CE-0A5D-4DCB-A6A6-7C8E92A6BD05}"> 8 @@ -84,6 +84,16 @@ DTS:DataType="8" xml:space="preserve"> + + + + + + + SQLTask:SqlStatementSource="INSERT INTO public."FOIMinistryRequests"( version, isactive, filenumber, description, recordsearchfromdate, recordsearchtodate, startdate, duedate, assignedto, created_at, updated_at, createdby, updatedby, programareaid, requeststatusid, foirequest_id, foirequestversion_id, cfrduedate, axisrequestid, requestpagecount, linkedrequests, migrationreference,assignedgroup,assignedministrygroup,identityverified,originalldd) VALUES ( 1, False, ?, ?, to_timestamp(?,'YYYY-MM-DD hh24:mi:ss'), to_timestamp(?,'YYYY-MM-DD hh24:mi:ss'), to_timestamp(?,'YYYY-MM-DD hh24:mi:ss'), to_timestamp(?,'YYYY-MM-DD hh24:mi:ss'), NULL, NOW(), NOW(), 'cfdmigration', 'cfdmigration', (SELECT programareaid FROM public."ProgramAreas" PA WHERE PA.iaocode='CFD' and PA.isactive=True), (SELECT requeststatusid FROM public."FOIRequestStatuses" RS WHERE RS.name='Open' and RS.isactive=True), (SELECT foirequestid FROM public."FOIRequests" R WHERE R.migrationreference=? ORDER BY R.created_at DESC LIMIT 1), (SELECT version FROM public."FOIRequests" R WHERE R.migrationreference=? ORDER BY R.created_at DESC LIMIT 1), to_timestamp(?,'YYYY-MM-DD hh24:mi:ss'), ?, ?, ?::json, ?,'Children and Family Team','MCF Ministry Team',?::json,to_timestamp(?,'YYYY-MM-DD hh24:mi:ss'));" xmlns:SQLTask="www.microsoft.com/sqlserver/dts/tasks/sqltask"> + + @@ -291,7 +323,7 @@ + SQLTask:SqlStatementSource="INSERT INTO public."FOIMinistryRequests"( foiministryrequestid, version, isactive, filenumber, description, recordsearchfromdate, recordsearchtodate, startdate, duedate, assignedto, created_at, updated_at, createdby, updatedby, programareaid, requeststatusid, foirequest_id, foirequestversion_id, cfrduedate, axisrequestid, requestpagecount, linkedrequests, migrationreference,assignedgroup,assignedministrygroup,identityverified,originalldd) VALUES ( (SELECT foiministryrequestid FROM public."FOIMinistryRequests" WHERE axisrequestid = ? LIMIT 1) , 2, True, ?, ?, to_timestamp(?,'YYYY-MM-DD hh24:mi:ss'), to_timestamp(?,'YYYY-MM-DD hh24:mi:ss'), to_timestamp(?,'YYYY-MM-DD hh24:mi:ss'), to_timestamp(?,'YYYY-MM-DD hh24:mi:ss'), NULL, NOW(), NOW(), 'cfdmigration', 'cfdmigration', (SELECT programareaid FROM public."ProgramAreas" PA WHERE PA.iaocode='CFD' and PA.isactive=True), (SELECT requeststatusid FROM public."FOIRequestStatuses" RS WHERE RS.name= (SELECT "stateonFOI" FROM public."AXISMigrationMapper" WHERE "stateonAXIS"=? LIMIT 1) and RS.isactive=True), (SELECT foirequestid FROM public."FOIRequests" R WHERE R.migrationreference=? ORDER BY R.created_at DESC LIMIT 1), (SELECT version FROM public."FOIRequests" R WHERE R.migrationreference=? ORDER BY R.created_at DESC LIMIT 1), to_timestamp(?,'YYYY-MM-DD hh24:mi:ss'), ?, ?, ?::json, ?,'Children and Family Team','MCF Ministry Team',?::json, to_timestamp(?,'YYYY-MM-DD hh24:mi:ss'));" xmlns:SQLTask="www.microsoft.com/sqlserver/dts/tasks/sqltask"> + + @@ -399,64 +443,76 @@ + + @@ -483,15 +539,15 @@ + DTS:VersionBuild="79" + DTS:VersionGUID="{963DE22B-D953-4B51-A23F-11B823D5F17A}"> 8 @@ -212,7 +212,7 @@ + DTS:ThreadHint="0"> + DTS:ThreadHint="1"> + DTS:ThreadHint="2"> + DTS:ThreadHint="7"> + DTS:ThreadHint="10"> + DTS:ThreadHint="8"> + DTS:ThreadHint="9"> + DTS:ThreadHint="5"> + DTS:ThreadHint="4"> + DTS:ThreadHint="3"> + DTS:ThreadHint="0"> + DTS:ThreadHint="7"> + DTS:ThreadHint="2"> + DTS:ThreadHint="10"> + DTS:ThreadHint="8"> + DTS:ThreadHint="9"> + DTS:ThreadHint="5"> + DTS:ThreadHint="4"> + DTS:ThreadHint="3"> + DTS:ThreadHint="1"> @@ -1255,7 +1255,7 @@ @@ -1291,7 +1291,7 @@ @@ -1327,7 +1327,7 @@ @@ -1351,7 +1351,7 @@ @@ -1466,8 +1466,8 @@ + DTS:VersionBuild="41" + DTS:VersionGUID="{6FF8FA79-F558-4AF0-BBF1-1939169A53C5}"> 8 @@ -143,7 +143,7 @@ + SQLTask:SqlStatementSource="INSERT INTO public."FOIRequests"( version, requesttype, receiveddate, isactive, initialdescription, initialrecordsearchfromdate, initialrecordsearchtodate, created_at, updated_at, createdby, updatedby, deliverymodeid, receivedmodeid, foirawrequestid, applicantcategoryid, wfinstanceid, migrationreference) VALUES ( 1, LOWER(?), to_timestamp(?,'YYYY-MM-DD hh24:mi:ss'), True, ?, to_timestamp(?,'YYYY-MM-DD hh24:mi:ss'), to_timestamp(?,'YYYY-MM-DD hh24:mi:ss'), NOW(), NOW(), 'cfdmigration', 'cfdmigration', 1, COALESCE((SELECT receivedmodeid FROM public."ReceivedModes" RM WHERE RM.name=?),1), -100, COALESCE((SELECT applicantcategoryid FROM public."ApplicantCategories" AC WHERE AC.name=?),2), NULL, ?);" xmlns:SQLTask="www.microsoft.com/sqlserver/dts/tasks/sqltask"> + DTS:ConnectionString="Data Source=Sphinx\CIRMO , 1435;Initial Catalog=ATIPIPROD;Provider=SQLNCLI11.1;Integrated Security=SSPI;Auto Translate=False;" /> \ No newline at end of file diff --git a/datamigrations/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration/Project.params b/datamigrations/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration/Project.params index 4d9e8eddd..941b54e10 100644 --- a/datamigrations/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration/Project.params +++ b/datamigrations/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration/Project.params @@ -16,7 +16,7 @@ 0 SELECT firstname,lastname,middleName,requesterid,CONVERT(varchar(MAX),'01-01-1900',120) as birthDate,businessName, GETDATE() as createdAt, 'cfdmigration' as createdBy,STRING_AGG(CAST(requestid as nvarchar(max)),', ') as requests ,MainApplicant FROM ( SELECT requesters.vcEmailID as email, requesters.iRequesterID as requesterid, requesters.vcFirstName as firstName, requesters.vcLastName as lastName, requesters.vcMiddleName as middleName, requestorfields.CUSTOMFIELD35 as birthDate, requesters.vcCompany as businessName, requests.vcVisibleRequestID as requestid, 1 as MainApplicant FROM tblRequests requests WITH (NOLOCK) LEFT OUTER JOIN EC_OFFICE office WITH (NOLOCK) ON requests.tiOfficeID = office.OFFICE_ID LEFT OUTER JOIN tblRequesters requesters WITH (NOLOCK) ON requests.iRequesterID = requesters.iRequesterID LEFT OUTER JOIN dbo.TBLREQUESTERCUSTOMFIELDS requestorfields WITH (NOLOCK) ON requesters.iRequesterID = requestorfields.IREQUESTERID WHERE office.OFFICE_CODE = 'CFD' AND requests.vcRequestStatus NOT IN ('Closed') AND requests.vcVisibleRequestID IN (@requestids) UNION ALL SELECT onbehalf.vcEmailID as email, onbehalf.iRequesterID as requesterid, onbehalf.vcFirstName as firstName, onbehalf.vcLastName as lastName, onbehalf.vcMiddleName as middleName, requestorfields.CUSTOMFIELD35 as birthDate, onbehalf.vcCompany as businessName, requests.vcVisibleRequestID as requestid, 0 as MainApplicant FROM tblRequests requests WITH (NOLOCK) LEFT OUTER JOIN EC_OFFICE office WITH (NOLOCK) ON requests.tiOfficeID = office.OFFICE_ID LEFT OUTER JOIN tblRequesters onbehalf WITH (NOLOCK) ON requests.iOnBehalfOf = onbehalf.iRequesterID LEFT OUTER JOIN dbo.TBLREQUESTERCUSTOMFIELDS requestorfields WITH (NOLOCK) ON onbehalf.iRequesterID = requestorfields.IREQUESTERID WHERE office.OFFICE_CODE = 'CFD' AND requests.vcRequestStatus NOT IN ('Closed') AND requests.vcVisibleRequestID IN (@requestids) and onbehalf.vcFirstName is NOT NULL ) AS T GROUP BY T.email,T.requesterid,T.firstname,T.lastname,T.middleName,T.requesterid,T.birthDate,T.businessName,T.MainApplicant ORDER BY T.firstname ASC + SSIS:Name="Value">SELECT firstname, lastname, middleName, requesterid, CONVERT(varchar(MAX),birthDate,120) as birthDate, businessName, GETDATE() as createdAt, 'cfdmigration' as createdBy, STRING_AGG(CAST(requestid as nvarchar(max)),', ') as requests , MainApplicant FROM ( SELECT requesters.vcEmailID as email, requesters.iRequesterID as requesterid, requesters.vcFirstName as firstName, requesters.vcLastName as lastName, requesters.vcMiddleName as middleName, requestorfields.CUSTOMFIELD35 as birthDate, requesters.vcCompany as businessName, requests.vcVisibleRequestID as requestid, 1 as MainApplicant FROM tblRequests requests WITH (NOLOCK) LEFT OUTER JOIN EC_OFFICE office WITH (NOLOCK) ON requests.tiOfficeID = office.OFFICE_ID LEFT OUTER JOIN tblRequesters requesters WITH (NOLOCK) ON requests.iRequesterID = requesters.iRequesterID LEFT OUTER JOIN dbo.TBLREQUESTERCUSTOMFIELDS requestorfields WITH (NOLOCK) ON requesters.iRequesterID = requestorfields.IREQUESTERID WHERE office.OFFICE_CODE = 'CFD' AND requests.vcRequestStatus NOT IN ('Closed') AND requests.vcVisibleRequestID IN (@requestids) UNION ALL SELECT onbehalf.vcEmailID as email, onbehalf.iRequesterID as requesterid, onbehalf.vcFirstName as firstName, onbehalf.vcLastName as lastName, onbehalf.vcMiddleName as middleName, requestorfields.CUSTOMFIELD35 as birthDate, onbehalf.vcCompany as businessName, requests.vcVisibleRequestID as requestid, 0 as MainApplicant FROM tblRequests requests WITH (NOLOCK) LEFT OUTER JOIN EC_OFFICE office WITH (NOLOCK) ON requests.tiOfficeID = office.OFFICE_ID LEFT OUTER JOIN tblRequesters onbehalf WITH (NOLOCK) ON requests.iOnBehalfOf = onbehalf.iRequesterID LEFT OUTER JOIN dbo.TBLREQUESTERCUSTOMFIELDS requestorfields WITH (NOLOCK) ON onbehalf.iRequesterID = requestorfields.IREQUESTERID WHERE office.OFFICE_CODE = 'CFD' AND requests.vcRequestStatus NOT IN ('Closed') AND requests.vcVisibleRequestID IN (@requestids) and onbehalf.vcFirstName is NOT NULL ) AS T GROUP BY T.email,T.requesterid,T.firstname,T.lastname,T.middleName,T.requesterid,T.birthDate,T.businessName,T.MainApplicant ORDER BY T.firstname ASC 18 @@ -37,7 +37,7 @@ 0 SELECT (SELECT terminology.vcTerminology from tblTerminologyLookup terminology WHERE terminology.iLabelID = requestTypes.iLabelID and terminology.tiLocaleID = 1) as requestType, convert(varchar, requests.sdtRequestedDate,120) as receivedDate, requests.vcDescription as requestdescription, convert(varchar,requests.sdtRqtDescFromdate,120) as reqDescriptionFromDate, convert(varchar,requests.sdtRqtDescTodate,120) as reqDescriptionToDate, (SELECT terminology.vcTerminology from tblTerminologyLookup terminology WHERE terminology.iLabelID = deliveryModes.iLabelID and terminology.tiLocaleID = 1) as deliveryMode, (SELECT terminology.vcTerminology from tblTerminologyLookup terminology WHERE terminology.iLabelID = receivedModes.iLabelID and terminology.tiLocaleID = 1) as receivedMode, requesterTypes.vcDescription as category, requests.vcVisibleRequestID as filenumber FROM tblRequests requests WITH (NOLOCK) LEFT OUTER JOIN EC_OFFICE office WITH (NOLOCK) ON requests.tiOfficeID = office.OFFICE_ID LEFT OUTER JOIN tblRequesterTypes requesterTypes WITH (NOLOCK) ON requests.tiRequesterCategoryID = requesterTypes.tiRequesterTypeID LEFT OUTER JOIN tblRequestStatuses requeststatuses WITH (NOLOCK) on requests.irequeststatusid = requeststatuses.irequeststatusid LEFT OUTER JOIN tblReceivedModes receivedModes WITH (NOLOCK) ON requests.tiReceivedType = receivedModes.tiReceivedModeID LEFT OUTER JOIN tblDeliveryModes deliveryModes WITH (NOLOCK) ON requests.tiDeliveryType = deliveryModes.tiDeliveryModeID LEFT OUTER JOIN tblRequestTypes requestTypes WITH (NOLOCK) ON requests.tiRequestTypeID = requestTypes.tiRequestTypeID WHERE vcVisibleRequestID IN (@requestids) AND office.OFFICE_CODE = 'CFD' AND requests.vcRequestStatus NOT IN ('Closed') GROUP BY requests.vcVisibleRequestID,requests.vcRequestStatus,requeststatuses.vcRequestStatus,requests.sdtReceivedDate, requests.sdtTargetDate, requests.sdtOriginalTargetDate, requests.vcDescription, requests.sdtRqtDescFromdate, requests.sdtRqtDescTodate, requests.sdtRequestedDate, office.OFFICE_CODE, requesterTypes.vcDescription, receivedModes.iLabelID, deliveryModes.iLabelID, requests.iRequestID, requestTypes.iLabelID, requests.vcVisibleRequestID, requests.tiOfficeID, office.OFFICE_ID + SSIS:Name="Value">SELECT (SELECT terminology.vcTerminology from tblTerminologyLookup terminology WHERE terminology.iLabelID = requestTypes.iLabelID and terminology.tiLocaleID = 1) as requestType, convert(varchar, requests.sdtRequestedDate,120) as receivedDate, requests.vcDescription as requestdescription, convert(varchar,ISNULL(requests.sdtRqtDescFromdate,''),120) as reqDescriptionFromDate, convert(varchar,ISNULL(requests.sdtRqtDescTodate,''),120) as reqDescriptionToDate, (SELECT terminology.vcTerminology from tblTerminologyLookup terminology WHERE terminology.iLabelID = deliveryModes.iLabelID and terminology.tiLocaleID = 1) as deliveryMode, ISNULL((SELECT REPLACE(terminology.vcTerminology,'-','') from tblTerminologyLookup terminology WHERE terminology.iLabelID = receivedModes.iLabelID and terminology.tiLocaleID = 1),'Email') as receivedMode, requesterTypes.vcDescription as category, requests.vcVisibleRequestID as filenumber FROM tblRequests requests WITH (NOLOCK) LEFT OUTER JOIN EC_OFFICE office WITH (NOLOCK) ON requests.tiOfficeID = office.OFFICE_ID LEFT OUTER JOIN tblRequesterTypes requesterTypes WITH (NOLOCK) ON requests.tiRequesterCategoryID = requesterTypes.tiRequesterTypeID LEFT OUTER JOIN tblRequestStatuses requeststatuses WITH (NOLOCK) on requests.irequeststatusid = requeststatuses.irequeststatusid LEFT OUTER JOIN tblReceivedModes receivedModes WITH (NOLOCK) ON requests.tiReceivedType = receivedModes.tiReceivedModeID LEFT OUTER JOIN tblDeliveryModes deliveryModes WITH (NOLOCK) ON requests.tiDeliveryType = deliveryModes.tiDeliveryModeID LEFT OUTER JOIN tblRequestTypes requestTypes WITH (NOLOCK) ON requests.tiRequestTypeID = requestTypes.tiRequestTypeID WHERE vcVisibleRequestID IN (@requestids) AND office.OFFICE_CODE = 'CFD' AND requests.vcRequestStatus NOT IN ('Closed','Completed') GROUP BY requests.vcVisibleRequestID,requests.vcRequestStatus,requeststatuses.vcRequestStatus,requests.sdtReceivedDate, requests.sdtTargetDate, requests.sdtOriginalTargetDate, requests.vcDescription, requests.sdtRqtDescFromdate, requests.sdtRqtDescTodate, requests.sdtRequestedDate, office.OFFICE_CODE, requesterTypes.vcDescription, receivedModes.iLabelID, deliveryModes.iLabelID,requests.iRequestID, requestTypes.iLabelID, requests.vcVisibleRequestID, requests.tiOfficeID, office.OFFICE_ID 18 @@ -58,7 +58,7 @@ 0 SELECT requests.vcVisibleRequestID as filenumber, requests.vcDescription as requestdescription, convert(varchar,requests.sdtRqtDescFromdate,120) as reqDescriptionFromDate, convert(varchar,requests.sdtRqtDescTodate,120) as reqDescriptionToDate, convert(varchar, requests.sdtReceivedDate,120) as requestProcessStart, convert(varchar,requests.sdtTargetDate,120) as dueDate, convert(varchar, (SELECT TOP 1 cfr.sdtDueDate FROM tblRequestForDocuments cfr WITH (NOLOCK) INNER JOIN tblProgramOffices programoffice WITH (NOLOCK) ON programoffice.tiProgramOfficeID = cfr.tiProgramOfficeID WHERE requests.iRequestID = cfr.iRequestID AND requests.tiOfficeID = programoffice.tiOfficeID AND office.OFFICE_ID = programoffice.tiOfficeID AND cfr.sdtDueDate IS NOT NULL ORDER BY cfr.sdtDueDate DESC),120) as cfrDueDate, convert(varchar,sum(distinct case when requests.IREQUESTID = reviewlog.IREQUESTID and reviewlog.IDOCID = documents.IDOCID then documents.SIPAGECOUNT when requests.IREQUESTID = redaction.IREQUESTID and redaction.IDOCID = ldocuments.IDOCID then ldocuments.SIPAGECOUNT else 0 end),120) as requestPageCount , requests.vcRequestStatus, CONVERT(VARCHAR(MAX),(SELECT CONCAT('[',STRING_AGG( CONCAT('{"', destin_vcVisibleRequestID, '":"', ministry, '"}'),','),']') AS linkedRequests FROM( SELECT DISTINCT destin.vcVisibleRequestID AS destin_vcVisibleRequestID, office.OFFICE_CODE AS ministry FROM tblRequests origin JOIN tblRequestLinks link ON(origin.IREQUESTID = link.iRequestIDOrigin OR origin.IREQUESTID = link.iRequestIDDestin) JOIN tblRequests destin ON(link.iRequestIDOrigin = destin.IREQUESTID OR link.iRequestIDDestin = destin.IREQUESTID) JOIN EC_OFFICE office ON destin.tiOfficeID = office.OFFICE_ID WHERE origin.vcVisibleRequestID = requests.vcVisibleRequestID AND destin.vcVisibleRequestID != requests.vcVisibleRequestID ) AS destination_table),120) AS linkedRequests FROM tblRequests requests WITH (NOLOCK) LEFT OUTER JOIN EC_OFFICE office WITH (NOLOCK) ON requests.tiOfficeID = office.OFFICE_ID LEFT OUTER JOIN tblRequestStatuses requeststatuses WITH (NOLOCK) on requests.irequeststatusid = requeststatuses.irequeststatusid LEFT OUTER JOIN dbo.TBLdocumentreviewlog reviewlog WITH (NOLOCK) ON requests.IREQUESTID = reviewlog.IREQUESTID LEFT OUTER JOIN dbo.TBLRedactionlayers redaction WITH (NOLOCK) ON requests.IREQUESTID = redaction.IREQUESTID LEFT OUTER JOIN dbo.TBLDOCUMENTS documents WITH (NOLOCK) ON reviewlog.IDOCID = documents.IDOCID LEFT OUTER JOIN dbo.TBLDOCUMENTS ldocuments WITH (NOLOCK) ON redaction.IDOCID = ldocuments.IDOCID WHERE vcVisibleRequestID IN (@requestids) AND office.OFFICE_CODE = 'CFD' AND requests.vcRequestStatus NOT IN ('Closed') GROUP BY requests.vcVisibleRequestID,requests.vcRequestStatus,requeststatuses.vcRequestStatus,requests.sdtReceivedDate, requests.sdtTargetDate, requests.sdtOriginalTargetDate, requests.vcDescription, requests.sdtRqtDescFromdate, requests.sdtRqtDescTodate, requests.sdtRequestedDate, office.OFFICE_CODE, requests.iRequestID, requests.vcVisibleRequestID, requests.tiOfficeID, office.OFFICE_ID,requests.vcRequestStatus + SSIS:Name="Value">SELECT requests.vcVisibleRequestID as filenumber, requests.vcDescription as requestdescription, convert(varchar,ISNULL(requests.sdtRqtDescFromdate,''),120) as reqDescriptionFromDate, convert(varchar,ISNULL(requests.sdtRqtDescTodate,''),120) as reqDescriptionToDate, convert(varchar, requests.sdtReceivedDate,120) as requestProcessStart, convert(varchar,requests.sdtTargetDate,120) as dueDate, convert(varchar, ISNULL((SELECT TOP 1 cfr.sdtDueDate FROM tblRequestForDocuments cfr WITH (NOLOCK) INNER JOIN tblProgramOffices programoffice WITH (NOLOCK) ON programoffice.tiProgramOfficeID = cfr.tiProgramOfficeID WHERE requests.iRequestID = cfr.iRequestID AND requests.tiOfficeID = programoffice.tiOfficeID AND office.OFFICE_ID = programoffice.tiOfficeID AND cfr.sdtDueDate IS NOT NULL ORDER BY cfr.sdtDueDate DESC),''),120) as cfrDueDate, convert(varchar,sum(distinct case when requests.IREQUESTID = reviewlog.IREQUESTID and reviewlog.IDOCID = documents.IDOCID then documents.SIPAGECOUNT when requests.IREQUESTID = redaction.IREQUESTID and redaction.IDOCID = ldocuments.IDOCID then ldocuments.SIPAGECOUNT else 0 end),120) as requestPageCount , requests.vcRequestStatus, CONVERT(VARCHAR(MAX),(SELECT CONCAT('[',STRING_AGG( CONCAT('{"', destin_vcVisibleRequestID, '":"', ministry, '"}'),','),']') AS linkedRequests FROM (SELECT DISTINCT destin.vcVisibleRequestID AS destin_vcVisibleRequestID, office.OFFICE_CODE AS ministry FROM tblRequests origin JOIN tblRequestLinks link ON(origin.IREQUESTID = link.iRequestIDOrigin OR origin.IREQUESTID = link.iRequestIDDestin) JOIN tblRequests destin ON(link.iRequestIDOrigin = destin.IREQUESTID OR link.iRequestIDDestin = destin.IREQUESTID) JOIN EC_OFFICE office ON destin.tiOfficeID = office.OFFICE_ID WHERE origin.vcVisibleRequestID = requests.vcVisibleRequestID AND destin.vcVisibleRequestID != requests.vcVisibleRequestID ) AS destination_table),120) AS linkedRequests, CONVERT(VARCHAR(MAX),CONCAT('"',ISNULL(requestfields.CUSTOMFIELD75,''),'"')) as identityVerified , convert(varchar,requests.sdtOriginalTargetDate,120) as originalDueDate FROM tblRequests requests WITH (NOLOCK) LEFT OUTER JOIN EC_OFFICE office WITH (NOLOCK) ON requests.tiOfficeID = office.OFFICE_ID LEFT OUTER JOIN tblRequestStatuses requeststatuses WITH (NOLOCK) on requests.irequeststatusid = requeststatuses.irequeststatusid LEFT OUTER JOIN dbo.TBLdocumentreviewlog reviewlog WITH (NOLOCK) ON requests.IREQUESTID = reviewlog.IREQUESTID LEFT OUTER JOIN dbo.TBLRedactionlayers redaction WITH (NOLOCK) ON requests.IREQUESTID = redaction.IREQUESTID LEFT OUTER JOIN dbo.TBLDOCUMENTS documents WITH (NOLOCK) ON reviewlog.IDOCID = documents.IDOCID LEFT OUTER JOIN dbo.TBLDOCUMENTS ldocuments WITH (NOLOCK) ON redaction.IDOCID = ldocuments.IDOCID LEFT OUTER JOIN dbo.TBLREQUESTCUSTOMFIELDS requestfields WITH (NOLOCK) ON requests.iRequestID = requestfields.iRequestID WHERE vcVisibleRequestID IN ( @requestids ) AND office.OFFICE_CODE = 'CFD' AND requests.vcRequestStatus NOT IN ('Closed','Completed') GROUP BY requests.vcVisibleRequestID,requests.vcRequestStatus,requeststatuses.vcRequestStatus,requests.sdtReceivedDate, requests.sdtTargetDate, requests.sdtOriginalTargetDate, requests.vcDescription, requests.sdtRqtDescFromdate, requests.sdtRqtDescTodate, requests.sdtRequestedDate, office.OFFICE_CODE, requests.iRequestID, requests.vcVisibleRequestID, requests.tiOfficeID, office.OFFICE_ID,requests.vcRequestStatus,requestfields.CUSTOMFIELD75 18 @@ -79,7 +79,7 @@ 0 SELECT loc.vcTerminology AS reason, reqextn.cApprovedStatus AS [status], convert(varchar, reqextn.sdtExtendedDate,120) AS extendedduedate, convert(varchar,reqextn.siExtensionDays) AS extensiondays, convert(varchar, reqextn.dtApprovedDate,120) AS decisiondate,req.vcVisibleRequestID as requestid FROM tblRequests req WITH (NOLOCK) INNER JOIN tblRequestExtensions reqextn WITH (NOLOCK) ON req.iRequestID = reqextn.iRequestID AND req.vcVisibleRequestID in (@requestids) INNER JOIN tblExtensions extn WITH (NOLOCK) ON reqextn.tiExtension = extn.tiExtension LEFT OUTER JOIN tblTerminologyLookup loc WITH (NOLOCK) ON loc.iLabelID = extn.iLabelID AND loc.tiLocaleID = 1; + SSIS:Name="Value">SELECT loc.vcTerminology AS reason, reqextn.cApprovedStatus AS [status], convert(varchar, reqextn.sdtExtendedDate,120) AS extendedduedate, convert(varchar,reqextn.siExtensionDays) AS extensiondays, convert(varchar, ISNULL(reqextn.dtApprovedDate,''),120) AS decisiondate,req.vcVisibleRequestID as requestid FROM tblRequests req WITH (NOLOCK) INNER JOIN tblRequestExtensions reqextn WITH (NOLOCK) ON req.iRequestID = reqextn.iRequestID and req.vcRequestStatus NOT IN ('Closed','Completed') AND req.vcVisibleRequestID in (@requestids) INNER JOIN tblExtensions extn WITH (NOLOCK) ON reqextn.tiExtension = extn.tiExtension LEFT OUTER JOIN tblTerminologyLookup loc WITH (NOLOCK) ON loc.iLabelID = extn.iLabelID AND loc.tiLocaleID = 1; 18 @@ -100,7 +100,7 @@ 0 SELECT email,address1,address2, city,zipcode,work1,work2,mobile,home,country,province, STRING_AGG(CAST(requestid as nvarchar(max)),', ') as requests FROM (SELECT 'test@test1.com' as email,requesters.vcAddress1 as address1, requesters.vcAddress2 as address2, requesters.vcCity as city, requesters.vcZipCode as zipcode, requesters.vcWork1 as work1, requesters.vcwork2 as work2, requesters.vcMobile as mobile,requesters.vcHome as home, (SELECT terminology.vcTerminology from tblTerminologyLookup terminology WHERE terminology.iLabelID = countries.iLabelID and terminology.tiLocaleID = 1) as country, (SELECT terminology.vcTerminology from tblTerminologyLookup terminology WHERE terminology.iLabelID = states.iLabelID and terminology.tiLocaleID = 1) as province, requests.vcVisibleRequestID as requestid FROM tblRequests requests WITH (NOLOCK) LEFT OUTER JOIN EC_OFFICE office WITH (NOLOCK) ON requests.tiOfficeID = office.OFFICE_ID LEFT OUTER JOIN tblRequesters requesters WITH (NOLOCK) ON requests.iRequesterID = requesters.iRequesterID LEFT OUTER JOIN tblCountries countries WITH (NOLOCK) ON requesters.siCountryID = countries.siCountryID LEFT OUTER JOIN tblStates states WITH (NOLOCK) ON requesters.siStateID = states.siStateID LEFT OUTER JOIN dbo.TBLREQUESTERCUSTOMFIELDS requestorfields WITH (NOLOCK) ON requesters.iRequesterID = requestorfields.IREQUESTERID WHERE office.OFFICE_CODE = 'CFD' AND requests.vcRequestStatus NOT IN ('Closed') ) AS T WHERE requestid in (@requestids) GROUP BY T.email,T.address1,T.address2, T.city,T.zipcode,T.work1,T.work2,T.mobile,T.home, T.country,T.province + SSIS:Name="Value">SELECT ISNULL(email,'') as email , ISNULL(address1,'') as address1, ISNULL(address2,'') as address2, ISNULL(city,'') as city, ISNULL(zipcode,'') as zipcode, ISNULL(work1,'') as work1, ISNULL(work2,'') as work2, ISNULL(mobile,'') as mobile, ISNULL(home,'') as home, ISNULL(country,'') as country, ISNULL(province, '') as province, STRING_AGG(CAST(requestid as nvarchar(max)),', ') as requests FROM ( SELECT requesters.vcEmailID as email, requesters.vcAddress1 as address1, requesters.vcAddress2 as address2, requesters.vcCity as city, requesters.vcZipCode as zipcode, requesters.vcWork1 as work1, requesters.vcwork2 as work2, requesters.vcMobile as mobile, requesters.vcHome as home, (SELECT terminology.vcTerminology from tblTerminologyLookup terminology WHERE terminology.iLabelID = countries.iLabelID and terminology.tiLocaleID = 1) as country, (SELECT terminology.vcTerminology from tblTerminologyLookup terminology WHERE terminology.iLabelID = states.iLabelID and terminology.tiLocaleID = 1) as province, requests.vcVisibleRequestID as requestid FROM tblRequests requests WITH (NOLOCK) LEFT OUTER JOIN EC_OFFICE office WITH (NOLOCK) ON requests.tiOfficeID = office.OFFICE_ID LEFT OUTER JOIN tblRequesters requesters WITH (NOLOCK) ON requests.iRequesterID = requesters.iRequesterID LEFT OUTER JOIN tblCountries countries WITH (NOLOCK) ON requesters.siCountryID = countries.siCountryID LEFT OUTER JOIN tblStates states WITH (NOLOCK) ON requesters.siStateID = states.siStateID LEFT OUTER JOIN dbo.TBLREQUESTERCUSTOMFIELDS requestorfields WITH (NOLOCK) ON requesters.iRequesterID = requestorfields.IREQUESTERID WHERE office.OFFICE_CODE = 'CFD' AND requests.vcRequestStatus NOT IN ('Closed') ) AS T WHERE requestid in (@requestids) GROUP BY T.email,T.address1,T.address2, T.city,T.zipcode,T.work1,T.work2,T.mobile,T.home, T.country,T.province 18 @@ -121,7 +121,7 @@ 0 'CFD-2021-12651','CFD-2023-30193' + SSIS:Name="Value"> 18 @@ -142,7 +142,91 @@ 0 SELECT vcVisibleRequestID , REPLACE(requestfields.CUSTOMFIELD33, CHAR(160), ' ') as subjectCode FROM tblRequests requests WITH (NOLOCK) LEFT OUTER JOIN dbo.TBLREQUESTCUSTOMFIELDS requestfields WITH (NOLOCK) ON requests.iRequestID = requestfields.iRequestID WHERE requests.vcVisibleRequestID in (@requestids) GROUP BY requests.vcVisibleRequestID, REPLACE(requestfields.CUSTOMFIELD33, CHAR(160), ' '); + SSIS:Name="Value">SELECT vcVisibleRequestID , REPLACE(requestfields.CUSTOMFIELD33, CHAR(160), ' ') as subjectCode FROM tblRequests requests WITH (NOLOCK) LEFT OUTER JOIN dbo.TBLREQUESTCUSTOMFIELDS requestfields WITH (NOLOCK) ON requests.iRequestID = requestfields.iRequestID WHERE requests.vcVisibleRequestID in (@requestids) and requests.vcRequestStatus NOT IN ('Closed','Completed') GROUP BY requests.vcVisibleRequestID, REPLACE(requestfields.CUSTOMFIELD33, CHAR(160), ' '); + 18 + + + + + {71721d3f-06a8-485b-9369-56a67f2665ba} + + + 0 + 0 + 0 + + 18 + + + + + {0b759d33-1caa-4e2a-91a1-2dcc73f0fcdb} + + + 0 + 0 + 0 + UPDATE public."FOIMinistryRequests" SET assignedgroup='Children and Education Team' WHERE migrationreference IS NOT NULL and axisrequestid in (@replacerequestids);commit; + 18 + + + + + {925253d6-2bbf-4c75-b780-ab97ea188e12} + + + 0 + 0 + 0 + SELECT R.vcVisibleRequestID, CONCAT(LOWER(U.[USER_NAME]),'@idir') FROM tblRequests R INNER JOIN EC_USERS U on R.iAssignedTo = U.USER_ID WHERE U.USER_CATEGORY_ID = 1 and R.vcVisibleRequestID in (@requestids) + 18 + + + + + {b1ee1a4b-7095-43ff-93e8-1a8372d11ee5} + + + 0 + 0 + 0 + SELECT DISTINCT CONCAT(LOWER(U.[USER_NAME]),'@idir') as analyst,U.FIRST_NAME,U.LAST_NAME,U.MIDDLE_NAME FROM tblRequests R INNER JOIN EC_USERS U on R.iAssignedTo = U.USER_ID WHERE U.USER_CATEGORY_ID = 1 and R.vcVisibleRequestID in (@requestids) ORDER BY analyst ASC 18 diff --git a/datamigrations/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration/UpdateRequestassignment.dtsx b/datamigrations/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration/UpdateRequestassignment.dtsx new file mode 100644 index 000000000..23720cdc4 --- /dev/null +++ b/datamigrations/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration/UpdateRequestassignment.dtsx @@ -0,0 +1,213 @@ + + + 8 + + + + + + + + + + + + + + + + + + + + + REPLACE( @[$Project::updateassignmentquery] ,"@requestids" , @[$Project::requestidstomigrate] ) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +]]> + \ No newline at end of file diff --git a/datamigrations/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration/UpdateTeamtoChildAndEducation.dtsx b/datamigrations/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration/UpdateTeamtoChildAndEducation.dtsx new file mode 100644 index 000000000..9f8e6a6f6 --- /dev/null +++ b/datamigrations/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration/UpdateTeamtoChildAndEducation.dtsx @@ -0,0 +1,67 @@ + + + 8 + + + + + REPLACE( @[$Project::updatetochildandeduteamquery] , "@replacerequestids", @[$Project::childrenandeducationrequests] ) + + + + + + + + + + + + + + + + + + + + +]]> + \ No newline at end of file diff --git a/datamigrations/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration/migrateassignees.dtsx b/datamigrations/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration/migrateassignees.dtsx new file mode 100644 index 000000000..abdd2b61e --- /dev/null +++ b/datamigrations/FOIMOD.CFD.ETL.DataMigration/FOIMOD.CFD.ETL.DataMigration/migrateassignees.dtsx @@ -0,0 +1,263 @@ + + + 8 + + + + + + + + + + + + + + + + + + + + + + + + + + + REPLACE( @[$Project::migrateassigneequery] ,"@requestids" , @[$Project::requestidstomigrate] ) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +]]> + \ No newline at end of file From f7960b10f0a60d58fbb59ffca97b37bada7205bb Mon Sep 17 00:00:00 2001 From: divyav-aot Date: Fri, 8 Dec 2023 11:42:17 -0500 Subject: [PATCH 05/22] updated the query sequence --- .../versions/d185518c3661_ state_label.py | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/request-management-api/migrations/versions/d185518c3661_ state_label.py b/request-management-api/migrations/versions/d185518c3661_ state_label.py index 9b1dd55ae..c0978c2af 100644 --- a/request-management-api/migrations/versions/d185518c3661_ state_label.py +++ b/request-management-api/migrations/versions/d185518c3661_ state_label.py @@ -129,20 +129,8 @@ def upgrade(): def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.execute('ALTER TABLE public."FOIRequestStatuses" drop column statuslabel;') - op.execute('ALTER TABLE public."FOIMinistryRequests" drop column requeststatuslabel;') - op.execute('ALTER TABLE public."FOIRawRequests" drop column requeststatuslabel;') - op.execute('ALTER TABLE public."FOIRequestTeams" drop column requeststatuslabel;') - - op.execute('DROP INDEX "FOIMinistryRequests_event";') - op.execute('CREATE INDEX "FOIMinistryRequests_event" ON "FOIMinistryRequests"(axisrequestid, assignedto, assignedgroup, assignedministryperson, assignedministrygroup, requeststatusid);') - - op.execute('DROP INDEX "FOIRawRequests_event";') - op.execute('CREATE INDEX "FOIRawRequests_event" ON "FOIRawRequests" (axisrequestid, assignedto, assignedgroup, status);') - - op.execute('DROP VIEW public."v_FOIRawRequests";') - op.execute('DROP VIEW public."v_FOIRequests";') - + op.execute('drop view public."v_FOIRequests" cascade;') + op.execute('drop view public."v_FOIRawRequests" cascade;') op.execute(""" CREATE OR REPLACE VIEW public."v_FOIRequests" AS SELECT DISTINCT ON (fr.foiministryrequestid) fr.foiministryrequestid, @@ -224,4 +212,15 @@ def downgrade(): ORDER BY fr.requestid, fr.version DESC, fr.axisrequestid) tmp WHERE tmp.status::text <> ALL (ARRAY['Archived'::character varying, 'Unopened'::character varying, 'Closed'::character varying]::text[]); """) + op.execute('ALTER TABLE public."FOIRequestStatuses" drop column statuslabel;') + op.execute('ALTER TABLE public."FOIMinistryRequests" drop column requeststatuslabel;') + op.execute('ALTER TABLE public."FOIRawRequests" drop column requeststatuslabel;') + op.execute('ALTER TABLE public."FOIRequestTeams" drop column requeststatuslabel;') + + op.execute('DROP INDEX "FOIMinistryRequests_event";') + op.execute('CREATE INDEX "FOIMinistryRequests_event" ON "FOIMinistryRequests"(axisrequestid, assignedto, assignedgroup, assignedministryperson, assignedministrygroup, requeststatusid);') + + op.execute('DROP INDEX "FOIRawRequests_event";') + op.execute('CREATE INDEX "FOIRawRequests_event" ON "FOIRawRequests" (axisrequestid, assignedto, assignedgroup, status);') + # ### end Alembic commands ### From d6de49072c495afd27130e905143ef4b5f292412 Mon Sep 17 00:00:00 2001 From: divyav-aot Date: Mon, 11 Dec 2023 13:49:37 -0500 Subject: [PATCH 06/22] bug fix - show requests in processing team queue --- .../request_api/models/FOIRawRequests.py | 91 ++++++++++++------- .../request_api/services/dashboardservice.py | 2 +- 2 files changed, 58 insertions(+), 35 deletions(-) diff --git a/request-management-api/request_api/models/FOIRawRequests.py b/request-management-api/request_api/models/FOIRawRequests.py index 9a0169647..b458f3dd7 100644 --- a/request-management-api/request_api/models/FOIRawRequests.py +++ b/request-management-api/request_api/models/FOIRawRequests.py @@ -18,6 +18,7 @@ import logging from dateutil import parser import json +from request_api.utils.enums import ProcessingTeamWithKeycloackGroup, IAOTeamWithKeycloackGroup class FOIRawRequest(db.Model): # Name of the table in our database @@ -429,7 +430,7 @@ def getstatenavigation(cls, requestid): return requeststates @classmethod - def getbasequery(cls, additionalfilter=None, userid=None, isiaorestrictedfilemanager=False): + def getbasequery(cls, additionalfilter=None, userid=None, isiaorestrictedfilemanager=False, groups=[]): _session = db.session #rawrequests @@ -575,43 +576,66 @@ def getbasequery(cls, additionalfilter=None, userid=None, isiaorestrictedfileman basequery = _session.query(*selectedcolumns).join(subquery_maxversion, and_(*joincondition)).join(FOIAssignee, FOIAssignee.username == FOIRawRequest.assignedto, isouter=True) + return FOIRawRequest.handleadditionalfilter(basequery, additionalfilter, userid, isiaorestrictedfilemanager, groups) + + @classmethod + def handleadditionalfilter(cls, basequery, additionalfilter=None, userid=None, isiaorestrictedfilemanager=False, groups=[]): if additionalfilter is None: + return FOIRawRequest.noadditionalfilter(basequery, userid, isiaorestrictedfilemanager) + else: + return FOIRawRequest.addadditionalfilter(basequery, additionalfilter, userid, isiaorestrictedfilemanager, groups) + + @classmethod + def noadditionalfilter(cls, basequery, userid=None, isiaorestrictedfilemanager=False): + if(isiaorestrictedfilemanager == True): + return basequery.filter(FOIRawRequest.status.notin_(['Archived'])) + else: + subquery_watchby = FOIRawRequestWatcher.getrequestidsbyuserid(userid) + + return basequery.join( + subquery_watchby, + subquery_watchby.c.requestid == FOIRawRequest.requestid, + isouter=True + ).filter( + and_( + FOIRawRequest.status.notin_(['Archived']), + or_( + FOIRawRequest.isiaorestricted == False, + and_(FOIRawRequest.isiaorestricted == True, FOIRawRequest.assignedto == userid), + and_(FOIRawRequest.isiaorestricted == True, subquery_watchby.c.watchedby == userid)))) + + @classmethod + def addadditionalfilter(cls, basequery, additionalfilter=None, userid=None, isiaorestrictedfilemanager=False, groups=[]): + isprocessingteam = False + if groups: + isprocessingteam = any(item in ProcessingTeamWithKeycloackGroup.list() for item in groups) + if(additionalfilter == 'watchingRequests' and userid is not None): + #watchby + subquery_watchby = FOIRawRequestWatcher.getrequestidsbyuserid(userid) + return basequery.join(subquery_watchby, subquery_watchby.c.requestid == FOIRawRequest.requestid).filter(FOIRawRequest.status.notin_(['Archived'])) + elif(additionalfilter == 'myRequests'): + #myrequest + return basequery.filter(and_(FOIRawRequest.status.notin_(['Archived']), FOIRawRequest.assignedto == userid)) + elif (additionalfilter.lower() == 'all' and isprocessingteam): if(isiaorestrictedfilemanager == True): return basequery.filter(FOIRawRequest.status.notin_(['Archived'])) else: - subquery_watchby = FOIRawRequestWatcher.getrequestidsbyuserid(userid) - - return basequery.join( - subquery_watchby, - subquery_watchby.c.requestid == FOIRawRequest.requestid, - isouter=True - ).filter( - and_( - FOIRawRequest.status.notin_(['Archived']), - or_( - FOIRawRequest.isiaorestricted == False, - and_(FOIRawRequest.isiaorestricted == True, FOIRawRequest.assignedto == userid), - and_(FOIRawRequest.isiaorestricted == True, subquery_watchby.c.watchedby == userid)))) + 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)))) else: - if(additionalfilter == 'watchingRequests' and userid is not None): - #watchby - subquery_watchby = FOIRawRequestWatcher.getrequestidsbyuserid(userid) - return basequery.join(subquery_watchby, subquery_watchby.c.requestid == FOIRawRequest.requestid).filter(FOIRawRequest.status.notin_(['Archived'])) - elif(additionalfilter == 'myRequests'): - #myrequest - return basequery.filter(and_(FOIRawRequest.status.notin_(['Archived']), FOIRawRequest.assignedto == userid)) + if(isiaorestrictedfilemanager == True): + return basequery.filter(FOIRawRequest.status.notin_(['Archived'])) else: - if(isiaorestrictedfilemanager == True): - return basequery.filter(FOIRawRequest.status.notin_(['Archived'])) - else: - return basequery.filter( - and_( - FOIRawRequest.status.notin_(['Archived']), - or_(FOIRawRequest.isiaorestricted == False, and_(FOIRawRequest.isiaorestricted == True, FOIRawRequest.assignedto == userid)))) + return basequery.filter( + and_( + FOIRawRequest.status.notin_(['Archived']), + or_(FOIRawRequest.isiaorestricted == False, and_(FOIRawRequest.isiaorestricted == True, FOIRawRequest.assignedto == userid)))) @classmethod - def getrequestssubquery(cls, filterfields, keyword, additionalfilter, userid, isiaorestrictedfilemanager): - basequery = FOIRawRequest.getbasequery(additionalfilter, userid, isiaorestrictedfilemanager) + def getrequestssubquery(cls, filterfields, keyword, additionalfilter, userid, isiaorestrictedfilemanager, groups): + basequery = FOIRawRequest.getbasequery(additionalfilter, userid, isiaorestrictedfilemanager, groups) basequery = basequery.filter(FOIRawRequest.status != 'Unopened').filter(FOIRawRequest.status != 'Closed') #filter/search if(len(filterfields) > 0 and keyword is not None): @@ -645,7 +669,7 @@ def getfilterforrequestssubquery(cls, filterfields, keyword): @classmethod - def getrequestspagination(cls, groups, page, size, sortingitems, sortingorders, filterfields, keyword, additionalfilter, userid, isiaorestrictedfilemanager, isministryrestrictedfilemanager=False): + def getrequestspagination(cls, groups, page, size, sortingitems, sortingorders, filterfields, keyword, additionalfilter, userid, isiaorestrictedfilemanager, usertype, isministryrestrictedfilemanager=False): #ministry requests iaoassignee = aliased(FOIAssignee) ministryassignee = aliased(FOIAssignee) @@ -653,10 +677,9 @@ def getrequestspagination(cls, groups, page, size, sortingitems, sortingorders, #sorting sortingcondition = FOIRawRequest.getsorting(sortingitems, sortingorders) - #rawrequests - if "Intake Team" in groups or groups is None: - subquery_rawrequest_queue = FOIRawRequest.getrequestssubquery(filterfields, keyword, additionalfilter, userid, isiaorestrictedfilemanager) + if usertype == "iao" or groups is None: + subquery_rawrequest_queue = FOIRawRequest.getrequestssubquery(filterfields, keyword, additionalfilter, userid, isiaorestrictedfilemanager, groups) query_full_queue = subquery_rawrequest_queue.union(subquery_ministry_queue) return query_full_queue.order_by(*sortingcondition).paginate(page=page, per_page=size) else: diff --git a/request-management-api/request_api/services/dashboardservice.py b/request-management-api/request_api/services/dashboardservice.py index ba2f913d1..a1ba54f0e 100644 --- a/request-management-api/request_api/services/dashboardservice.py +++ b/request-management-api/request_api/services/dashboardservice.py @@ -69,7 +69,7 @@ def __preparebaserequestinfo(self, id, requesttype, status, receiveddate, receiv } def getrequestqueuepagination(self, groups=None, page=1, size=10, sortingitems=[], sortingorders=[], filterfields=[], keyword=None, additionalfilter='All', userid=None): - requests = FOIRawRequest.getrequestspagination(groups, page, size, sortingitems, sortingorders, filterfields, keyword, additionalfilter, userid, AuthHelper.isiaorestrictedfilemanager()) + requests = FOIRawRequest.getrequestspagination(groups, page, size, sortingitems, sortingorders, filterfields, keyword, additionalfilter, userid, AuthHelper.isiaorestrictedfilemanager(), AuthHelper.getusertype()) requestqueue = [] for request in requests.items: From 19fd9806e8146a16469b5b03b75805bc115f2cc3 Mon Sep 17 00:00:00 2001 From: divyav-aot Date: Mon, 11 Dec 2023 13:51:48 -0500 Subject: [PATCH 07/22] refactored the code --- request-management-api/request_api/models/FOIRawRequests.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/request-management-api/request_api/models/FOIRawRequests.py b/request-management-api/request_api/models/FOIRawRequests.py index b458f3dd7..4615ae764 100644 --- a/request-management-api/request_api/models/FOIRawRequests.py +++ b/request-management-api/request_api/models/FOIRawRequests.py @@ -580,10 +580,9 @@ def getbasequery(cls, additionalfilter=None, userid=None, isiaorestrictedfileman @classmethod def handleadditionalfilter(cls, basequery, additionalfilter=None, userid=None, isiaorestrictedfilemanager=False, groups=[]): - if additionalfilter is None: - return FOIRawRequest.noadditionalfilter(basequery, userid, isiaorestrictedfilemanager) - else: + if additionalfilter: return FOIRawRequest.addadditionalfilter(basequery, additionalfilter, userid, isiaorestrictedfilemanager, groups) + return FOIRawRequest.noadditionalfilter(basequery, userid, isiaorestrictedfilemanager) @classmethod def noadditionalfilter(cls, basequery, userid=None, isiaorestrictedfilemanager=False): From bcfe3590d1590990b509401cdf3286407e62fdd3 Mon Sep 17 00:00:00 2001 From: divyav-aot Date: Mon, 11 Dec 2023 14:43:30 -0500 Subject: [PATCH 08/22] fixed the bug to show only the request belong to intake should show in intake team/user queue --- .../request_api/models/FOIRawRequests.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/request-management-api/request_api/models/FOIRawRequests.py b/request-management-api/request_api/models/FOIRawRequests.py index 4615ae764..83fe842c9 100644 --- a/request-management-api/request_api/models/FOIRawRequests.py +++ b/request-management-api/request_api/models/FOIRawRequests.py @@ -606,8 +606,10 @@ def noadditionalfilter(cls, basequery, userid=None, isiaorestrictedfilemanager=F @classmethod def addadditionalfilter(cls, basequery, additionalfilter=None, userid=None, isiaorestrictedfilemanager=False, groups=[]): isprocessingteam = False + if groups: isprocessingteam = any(item in ProcessingTeamWithKeycloackGroup.list() for item in groups) + if(additionalfilter == 'watchingRequests' and userid is not None): #watchby subquery_watchby = FOIRawRequestWatcher.getrequestidsbyuserid(userid) @@ -615,14 +617,19 @@ def addadditionalfilter(cls, basequery, additionalfilter=None, userid=None, isia elif(additionalfilter == 'myRequests'): #myrequest return basequery.filter(and_(FOIRawRequest.status.notin_(['Archived']), FOIRawRequest.assignedto == userid)) - elif (additionalfilter.lower() == 'all' and isprocessingteam): + elif (additionalfilter.lower() == 'all'): if(isiaorestrictedfilemanager == True): return basequery.filter(FOIRawRequest.status.notin_(['Archived'])) else: + if isprocessingteam: + 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)))) 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 == "Intake Team"), and_(FOIRawRequest.isiaorestricted == True, FOIRawRequest.assignedto == userid)))) else: if(isiaorestrictedfilemanager == True): return basequery.filter(FOIRawRequest.status.notin_(['Archived'])) @@ -635,6 +642,7 @@ def addadditionalfilter(cls, basequery, additionalfilter=None, userid=None, isia @classmethod def getrequestssubquery(cls, filterfields, keyword, additionalfilter, userid, isiaorestrictedfilemanager, groups): basequery = FOIRawRequest.getbasequery(additionalfilter, userid, isiaorestrictedfilemanager, groups) + print(f"basequery = {basequery}") basequery = basequery.filter(FOIRawRequest.status != 'Unopened').filter(FOIRawRequest.status != 'Closed') #filter/search if(len(filterfields) > 0 and keyword is not None): From 73da845c72a65b8aa8f69fca4b7f099d508ad54f Mon Sep 17 00:00:00 2001 From: divyav-aot Date: Mon, 11 Dec 2023 16:54:21 -0500 Subject: [PATCH 09/22] fix issue related to assignment --- request-management-api/request_api/models/FOIRawRequests.py | 5 +++-- request-management-api/request_api/resources/request.py | 5 ++--- .../request_api/services/rawrequestservice.py | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/request-management-api/request_api/models/FOIRawRequests.py b/request-management-api/request_api/models/FOIRawRequests.py index b7588d84c..cb919036c 100644 --- a/request-management-api/request_api/models/FOIRawRequests.py +++ b/request-management-api/request_api/models/FOIRawRequests.py @@ -148,6 +148,7 @@ def saveiaorestrictedrawrequest(cls,requestid,_isiaorestricted=False, _updatedby requirespayment = request.requirespayment, isiaorestricted =_isiaorestricted, notes = request.notes, + requeststatuslabel = request.requeststatuslabel, ) ) @@ -194,8 +195,8 @@ def saverawrequestassigneeversion(cls,requestid,assigneegroup,assignee,userid,as axisrequestid= axisrequestid, axissyncdate=axissyncdate, linkedrequests=linkedrequests, - isiaorestricted = request.isiaorestricted - + isiaorestricted = request.isiaorestricted, + requeststatuslabel = request.requeststatuslabel ) ) db.session.execute(insertstmt) diff --git a/request-management-api/request_api/resources/request.py b/request-management-api/request_api/resources/request.py index 58768694a..fcec8a2e5 100644 --- a/request-management-api/request_api/resources/request.py +++ b/request-management-api/request_api/resources/request.py @@ -94,10 +94,9 @@ def post(requestid=None, actiontype=None): assigneemiddlename = requestdata['assigneemiddlename'] assigneelastname = requestdata['assigneelastname'] statuslabel = requestdata['requeststatuslabel'] - if int(requestid) and str(requestid) != "-1" : - status = rawrequestservice().getstatus(updaterequest) - if statuslabel not in [StateName.intakeinprogress.name, StateName.closed.name, StateName.redirect.name, StateName.peerreview.name, StateName.section5pending.name, StateName.appfeeowing.name]: + status, statuslabel = rawrequestservice().getstatus(updaterequest) + if status not in [StateName.intakeinprogress.value, StateName.closed.value, StateName.redirect.value, StateName.peerreview.value, StateName.section5pending.value, StateName.appfeeowing.value]: raise ValueError('Invalid request state.') result = rawrequestservice().saverawrequestversion(updaterequest,requestid,assigneegroup,assignee,status,AuthHelper.getuserid(),assigneefirstname,assigneemiddlename,assigneelastname, statuslabel, actiontype) assignee = '' diff --git a/request-management-api/request_api/services/rawrequestservice.py b/request-management-api/request_api/services/rawrequestservice.py index 1c0564733..c39c67b85 100644 --- a/request-management-api/request_api/services/rawrequestservice.py +++ b/request-management-api/request_api/services/rawrequestservice.py @@ -129,7 +129,7 @@ def getstatus(self, foirequest): statuslabel = foirequest["requeststatuslabel"] if "requeststatuslabel" in foirequest else None if statuslabel is not None: try: - return requestserviceconfigurator().getstatusname(statuslabel) + return requestserviceconfigurator().getstatusname(statuslabel), statuslabel # if statusid== 4: # return 'Redirect' # if statusid == 3: @@ -138,7 +138,7 @@ def getstatus(self, foirequest): # return 'Peer Review' except KeyError: print("Key Error on requeststatusid, ignore will be intake in Progress") - return StateName.intakeinprogress.value + return StateName.intakeinprogress.value, StateName.intakeinprogress.name def getaxisequestids(self): return rawrequestservicegetter().getaxisequestids() From ef04d7a673a8fc64d842b155fb593dc4de575558 Mon Sep 17 00:00:00 2001 From: divyav-aot Date: Thu, 23 Nov 2023 17:59:15 -0500 Subject: [PATCH 10/22] migration script for statelabel --- .../versions/d185518c3661_ state_label.py | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 request-management-api/migrations/versions/d185518c3661_ state_label.py diff --git a/request-management-api/migrations/versions/d185518c3661_ state_label.py b/request-management-api/migrations/versions/d185518c3661_ state_label.py new file mode 100644 index 000000000..36814855b --- /dev/null +++ b/request-management-api/migrations/versions/d185518c3661_ state_label.py @@ -0,0 +1,47 @@ +"""empty message + +Revision ID: d185518c3661 +Revises: 7fa7236d06fb +Create Date: 2023-06-01 22:31:24.595281 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = 'd185518c3661' +down_revision = '7fa7236d06fb' + +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.execute('ALTER TABLE public."FOIRequestStatuses" ADD COLUMN statuslabel VARCHAR(50);') + op.execute('UPDATE public."FOIRequestStatuses" SET statuslabel = REPLACE(LOWER(name), \' \', \'\');') + op.execute('ALTER TABLE public."FOIRequestStatuses" ALTER COLUMN statuslabel SET NOT NULL;') + op.execute('ALTER TABLE public."FOIRequestStatuses" ADD CONSTRAINT unique_statuslabel UNIQUE (statuslabel);') + + op.execute('ALTER TABLE public."FOIMinistryRequests" ADD COLUMN requeststatuslabel VARCHAR(50);') + op.execute('UPDATE public."FOIMinistryRequests" AS mr SET requeststatuslabel = st.statuslabel FROM public."FOIRequestStatuses" AS st WHERE mr.requeststatusid = st.requeststatusid;') + op.execute('ALTER TABLE public."FOIMinistryRequests" ALTER COLUMN requeststatuslabel SET NOT NULL;') + + op.execute('ALTER TABLE public."FOIRawRequests" ADD COLUMN requeststatuslabel VARCHAR(50);') + op.execute('UPDATE public."FOIRawRequests" SET requeststatuslabel = REPLACE(LOWER(status), \' \', \'\');') + op.execute('ALTER TABLE public."FOIRawRequests" ALTER COLUMN requeststatuslabel SET NOT NULL;') + + op.execute('ALTER TABLE public."FOIRequestTeams" ADD COLUMN requeststatuslabel VARCHAR(50);') + op.execute('UPDATE public."FOIRequestTeams" AS rt SET requeststatuslabel = st.statuslabel FROM public."FOIRequestStatuses" AS st WHERE rt.requeststatusid = st.requeststatusid;') + op.execute('ALTER TABLE public."FOIRequestTeams" ALTER COLUMN requeststatuslabel SET NOT NULL;') + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.execute('ALTER TABLE public."FOIRequestStatuses" drop column statuslabel;') + op.execute('ALTER TABLE public."FOIMinistryRequests" drop column requeststatuslabel;') + op.execute('ALTER TABLE public."FOIRawRequests" drop column requeststatuslabel;') + op.execute('ALTER TABLE public."FOIRequestTeams" drop column requeststatuslabel;') + # ### end Alembic commands ### From 2fef1e6a51b894b02d6e7e529854003ed56479d7 Mon Sep 17 00:00:00 2001 From: divyav-aot Date: Tue, 12 Dec 2023 11:49:13 -0500 Subject: [PATCH 11/22] fixed migration script issue --- .../migrations/versions/d185518c3661_ state_label.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/request-management-api/migrations/versions/d185518c3661_ state_label.py b/request-management-api/migrations/versions/d185518c3661_ state_label.py index c0978c2af..6de636d0a 100644 --- a/request-management-api/migrations/versions/d185518c3661_ state_label.py +++ b/request-management-api/migrations/versions/d185518c3661_ state_label.py @@ -129,8 +129,8 @@ def upgrade(): def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.execute('drop view public."v_FOIRequests" cascade;') op.execute('drop view public."v_FOIRawRequests" cascade;') + op.execute('drop view public."v_FOIRequests" cascade;') op.execute(""" CREATE OR REPLACE VIEW public."v_FOIRequests" AS SELECT DISTINCT ON (fr.foiministryrequestid) fr.foiministryrequestid, From 4bc1107b243d011f5743ed7727f1717c8f588275 Mon Sep 17 00:00:00 2001 From: Shivakumar Date: Thu, 30 Nov 2023 12:30:58 -0800 Subject: [PATCH 12/22] Update notification refactoring --- .../common/notificationtypes.json | 142 ++++++++++++++++++ .../common/notificationusertypes.json | 30 ++++ .../dao/models/FOIRequestNotificationUsers.py | 6 +- .../dao/models/FOIRequestNotifications.py | 6 +- .../dao/models/NotificationTypes.py | 2 +- .../dao/models/NotificationUserTypes.py | 27 ++++ .../notifications/notificationconfig.py | 26 +--- .../notifications/notificationuser.py | 12 +- .../services/notificationservice.py | 4 +- .../common/notificationtypes.json | 142 ++++++++++++++++++ .../common/notificationusertypes.json | 30 ++++ .../migrations/versions/29b44e8dc305_.py | 59 ++++++++ .../models/FOIRawRequestNotificationUsers.py | 16 +- .../models/FOIRawRequestNotifications.py | 16 +- .../models/FOIRequestNotificationUsers.py | 18 +-- .../models/FOIRequestNotifications.py | 41 ++--- .../request_api/models/NotificationTypes.py | 11 +- .../models/NotificationUserTypes.py | 10 +- .../models/views/FOINotifications.py | 1 + .../notifications/notificationconfig.py | 54 ++----- .../notifications/notificationuser.py | 12 +- .../services/notificationservice.py | 31 ++-- 22 files changed, 555 insertions(+), 141 deletions(-) create mode 100644 notification-manager/common/notificationtypes.json create mode 100644 notification-manager/common/notificationusertypes.json create mode 100644 notification-manager/notification_api/dao/models/NotificationUserTypes.py create mode 100644 request-management-api/common/notificationtypes.json create mode 100644 request-management-api/common/notificationusertypes.json create mode 100644 request-management-api/migrations/versions/29b44e8dc305_.py diff --git a/notification-manager/common/notificationtypes.json b/notification-manager/common/notificationtypes.json new file mode 100644 index 000000000..5c04ecec7 --- /dev/null +++ b/notification-manager/common/notificationtypes.json @@ -0,0 +1,142 @@ +{ + "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" + } +} diff --git a/notification-manager/common/notificationusertypes.json b/notification-manager/common/notificationusertypes.json new file mode 100644 index 000000000..0ea835c44 --- /dev/null +++ b/notification-manager/common/notificationusertypes.json @@ -0,0 +1,30 @@ +{ + "watcher": { + "notificationusertypeid": 1, + "name": "Watcher", + "description": "Watcher", + "isactive": true, + "notificationusertypelabel": "watcher" + }, + "assignee": { + "notificationusertypeid": 2, + "name": "Assignee", + "description": "Assignee", + "isactive": true, + "notificationusertypelabel": "assignee" + }, + "commentuser": { + "notificationusertypeid": 3, + "name": "Comment User", + "description": "Comment User", + "isactive": true, + "notificationusertypelabel": "commentuser" + }, + "triggereduser": { + "notificationusertypeid": 4, + "name": "Triggered User", + "description": "Triggered User", + "isactive": true, + "notificationusertypelabel": "triggereduser" + } +} diff --git a/notification-manager/notification_api/dao/models/FOIRequestNotificationUsers.py b/notification-manager/notification_api/dao/models/FOIRequestNotificationUsers.py index df9bd1737..b1c688834 100644 --- a/notification-manager/notification_api/dao/models/FOIRequestNotificationUsers.py +++ b/notification-manager/notification_api/dao/models/FOIRequestNotificationUsers.py @@ -11,7 +11,7 @@ class Meta: # pylint: disable=too-few-public-methods unknown = EXCLUDE notificationid = fields.Int(data_key="notificationid") userid = fields.Str(data_key="userid") - notificationusertypeid = fields.Int(data_key="notificationusertypeid") + notificationusertypelabel = fields.Int(data_key="notificationusertypelabel") createdby = fields.Str(data_key="createdby") created_at = fields.Str(data_key="created_at") isdeleted = fields.Boolean(data_key="isdeleted") @@ -21,9 +21,9 @@ def savenotificationuser(self, notificationuser): try: conn = getconnection() cursor = conn.cursor() - cursor.execute('INSERT INTO public."FOIRequestNotificationUsers" (notificationid, userid, notificationusertypeid, createdby, created_at, isdeleted) \ + cursor.execute('INSERT INTO public."FOIRequestNotificationUsers" (notificationid, userid, notificationusertypeid, notificationusertypelabel, createdby, created_at, isdeleted) \ VALUES(%s::integer, %s, %s::integer, %s, %s, %s::boolean)', - (int(notificationuser.notificationid), str(notificationuser.userid), int(notificationuser.notificationusertypeid), str(notificationuser.createdby), datetime.now(), int(notificationuser.isdeleted))) + (int(notificationuser.notificationid), str(notificationuser.userid), int(notificationuser.notificationusertypeid), str(notificationuser.notificationusertypelabel), str(notificationuser.createdby), datetime.now(), int(notificationuser.isdeleted))) conn.commit() cursor.close() except(Exception) as error: diff --git a/notification-manager/notification_api/dao/models/FOIRequestNotifications.py b/notification-manager/notification_api/dao/models/FOIRequestNotifications.py index 7cfa7b643..df7db942a 100644 --- a/notification-manager/notification_api/dao/models/FOIRequestNotifications.py +++ b/notification-manager/notification_api/dao/models/FOIRequestNotifications.py @@ -13,7 +13,7 @@ class Meta: # pylint: disable=too-few-public-methods requestid = fields.Int(data_key="requestid") idnumber = fields.Str(data_key="idnumber") foirequestid = fields.Int(data_key="foirequestid") - notificationtypeid = fields.Int(data_key="notificationtypeid") + notificationtypelabel = fields.Int(data_key="notificationtypelabel") axisnumber = fields.Str(data_key="axisnumber") version = fields.Int(data_key="version") notification = fields.Str(data_key="notification") @@ -26,9 +26,9 @@ def savenotification(self, notificationschema): id_of_new_row = None conn = getconnection() cursor = conn.cursor() - cursor.execute('INSERT INTO public."FOIRequestNotifications" (notification, notificationtypeid, requestid, "version", idnumber, axisnumber, foirequestid, createdby, created_at) \ + cursor.execute('INSERT INTO public."FOIRequestNotifications" (notification, notificationtypelabel, requestid, "version", idnumber, axisnumber, foirequestid, createdby, created_at) \ VALUES(%s::json,%s::integer, %s::integer, %s::integer,%s,%s,%s::integer,%s,%s) RETURNING notificationid', - (json.dumps(notificationschema.notification), int(notificationschema.notificationtypeid), int(notificationschema.requestid), int(notificationschema.version), + (json.dumps(notificationschema.notification), int(notificationschema.notificationtypelabel), int(notificationschema.requestid), int(notificationschema.version), str(notificationschema.idnumber), str(notificationschema.axisnumber), int(notificationschema.foirequestid), str(notificationschema.createdby), datetime.now())) conn.commit() diff --git a/notification-manager/notification_api/dao/models/NotificationTypes.py b/notification-manager/notification_api/dao/models/NotificationTypes.py index 7fdc577b3..e2db41f92 100644 --- a/notification-manager/notification_api/dao/models/NotificationTypes.py +++ b/notification-manager/notification_api/dao/models/NotificationTypes.py @@ -11,7 +11,7 @@ def getid(self, name): _notificationtypes = [] conn = getconnection() cursor = conn.cursor() - cursor.execute("""select notificationtypeid from "NotificationTypes" nt where isactive = true and name = '{0}'""".format(name)) + cursor.execute("""select notificationtypelabel from "NotificationTypes" nt where isactive = true and name = '{0}'""".format(name)) data = cursor.fetchone() if data is not None: return data[0] diff --git a/notification-manager/notification_api/dao/models/NotificationUserTypes.py b/notification-manager/notification_api/dao/models/NotificationUserTypes.py new file mode 100644 index 000000000..ee9719aac --- /dev/null +++ b/notification-manager/notification_api/dao/models/NotificationUserTypes.py @@ -0,0 +1,27 @@ +''' +This file is used in the notification manager container +to fetch the data models for the NotificationUserTypes table +''' +from datetime import datetime +from notification_api.dao.db import getconnection +import logging + +class NotificationUserType(object): + def getid(self, name): + conn = None + try: + _notificationusertypes = [] + conn = getconnection() + cursor = conn.cursor() + cursor.execute("""select notificationusertypelabel from "NotificationUserTypes" nt where isactive = true and name = '{0}'""".format(name)) + data = cursor.fetchone() + if data is not None: + return data[0] + + 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 42cc40736..e6be3ef60 100644 --- a/notification-manager/notification_api/services/notifications/notificationconfig.py +++ b/notification-manager/notification_api/services/notifications/notificationconfig.py @@ -4,6 +4,7 @@ import json import os from notification_api.dao.models.NotificationTypes import NotificationType +from notification_api.dao.models.NotificationUserTypes import NotificationUserType class notificationconfig: """ Notfication config @@ -11,27 +12,14 @@ class notificationconfig: """ def getnotificationtypeid(self, notificationtype): - - if "IAO Assignment" in notificationtype: - return 5 - elif "Ministry Assignment" in notificationtype: - return 6 - else: - notificationid = NotificationType().getid(notificationtype) - if notificationid is not None: - return notificationid - return 0 + notificationid = NotificationType().getid(notificationtype) + if notificationid is not None: + return notificationid def getnotificationusertypeid(self, notificationusertype): - if notificationusertype.lower() == "watcher": - return 1 - elif notificationusertype.lower() == "assignee" or "comment" or "group members" in notificationusertype.lower(): - return 2 - elif notificationusertype.lower() == "comment user": - return 3 - elif notificationusertype.lower() == "triggered user": - return 4 - return 0 + notificationuserid = NotificationUserType().getid(notificationusertype) + if notificationuserid is not None: + return notificationuserid def getnotificationdays(self): if 'FOI_NOTIFICATION_DAYS' in os.environ and 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 4618dc4d3..974930cc5 100644 --- a/notification-manager/notification_api/services/notifications/notificationuser.py +++ b/notification-manager/notification_api/services/notifications/notificationuser.py @@ -73,14 +73,14 @@ def __getwatchers(self, notificationtype, foirequest, requesttype, requestjson=N def __getassignees(self, foirequest, requesttype, notificationtype, requestjson=None): notificationusers = [] - notificationtypeid = notificationconfig().getnotificationusertypeid("Assignee") + notificationtypelabel = notificationconfig().getnotificationusertypeid("Assignee") if notificationtype == 'User Assignment Removal': - notificationusers.append({"userid": requestjson['userid'], "usertype":notificationtypeid}) + notificationusers.append({"userid": requestjson['userid'], "usertype":notificationtypelabel}) 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":notificationtypeid}) + notificationusers.append({"userid":foirequest["assignedministryperson"], "usertype":notificationtypelabel}) if foirequest["assignedto"] is not None and foirequest["assignedto"] != '' and (notificationtype == 'IAO Assignment' or 'Assignment' not in notificationtype): - notificationusers.append({"userid":foirequest["assignedto"], "usertype":notificationtypeid}) + notificationusers.append({"userid":foirequest["assignedto"], "usertype":notificationtypelabel}) return notificationusers def __getcommentusers(self, foirequest, comment, requesttype): @@ -126,9 +126,9 @@ def __preparetaggeduser(self, data): def __getgroupmembers(self,groupid): notificationusers = [] - notificationtypeid = notificationconfig().getnotificationusertypeid("Group Members") + notificationtypelabel = notificationconfig().getnotificationusertypeid("Group Members") usergroupfromkeycloak= KeycloakAdminService().getmembersbygroupname(groupid) for user in usergroupfromkeycloak[0].get("members"): - notificationusers.append({"userid":user["username"], "usertype":notificationtypeid}) + notificationusers.append({"userid":user["username"], "usertype":notificationtypelabel}) return notificationusers \ No newline at end of file diff --git a/notification-manager/notification_api/services/notificationservice.py b/notification-manager/notification_api/services/notificationservice.py index 8c46a8fff..d4871ce3f 100644 --- a/notification-manager/notification_api/services/notificationservice.py +++ b/notification-manager/notification_api/services/notificationservice.py @@ -65,7 +65,7 @@ def __preparenotification(self, message, requesttype, notificationtype, userid, notification.requestid = foirequest["foiministryrequestid"] notification.idnumber = foirequest["filenumber"] notification.foirequestid = foirequest["foirequest_id"] - notification.notificationtypeid = notificationconfig().getnotificationtypeid(notificationtype) + notification.notificationtypelabel = notificationconfig().getnotificationtypelabel(notificationtype) notification.axisnumber = foirequest["axisrequestid"] notification.version = foirequest["version"] notification.createdby = userid @@ -79,7 +79,7 @@ def __preparenotificationuser(self, notificationid, notificationuser, userid, mu user.isdeleted = mute else: user.isdeleted = False - user.notificationusertypeid = notificationuser["usertype"] + user.notificationusertypelabel = notificationuser["usertype"] user.notificationid = notificationid user.userid = notificationuser["userid"] user.createdby = userid diff --git a/request-management-api/common/notificationtypes.json b/request-management-api/common/notificationtypes.json new file mode 100644 index 000000000..5c04ecec7 --- /dev/null +++ b/request-management-api/common/notificationtypes.json @@ -0,0 +1,142 @@ +{ + "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" + } +} diff --git a/request-management-api/common/notificationusertypes.json b/request-management-api/common/notificationusertypes.json new file mode 100644 index 000000000..0ea835c44 --- /dev/null +++ b/request-management-api/common/notificationusertypes.json @@ -0,0 +1,30 @@ +{ + "watcher": { + "notificationusertypeid": 1, + "name": "Watcher", + "description": "Watcher", + "isactive": true, + "notificationusertypelabel": "watcher" + }, + "assignee": { + "notificationusertypeid": 2, + "name": "Assignee", + "description": "Assignee", + "isactive": true, + "notificationusertypelabel": "assignee" + }, + "commentuser": { + "notificationusertypeid": 3, + "name": "Comment 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/migrations/versions/29b44e8dc305_.py b/request-management-api/migrations/versions/29b44e8dc305_.py new file mode 100644 index 000000000..cb7400207 --- /dev/null +++ b/request-management-api/migrations/versions/29b44e8dc305_.py @@ -0,0 +1,59 @@ +"""empty message + +Revision ID: 29b44e8dc305 +Revises: +Create Date: 2021-07-08 10:08:53.028617 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '29b44e8dc305' +down_revision = 'd185518c3661' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.execute('ALTER TABLE public."NotificationTypes" ADD COLUMN notificationtypelabel VARCHAR(50);') + op.execute('UPDATE public."NotificationTypes" SET notificationtypelabel = REPLACE(LOWER(name), \' \', \'\');') + op.execute('ALTER TABLE public."NotificationTypes" ALTER COLUMN notificationtypelabel SET NOT NULL;') + op.execute('ALTER TABLE public."NotificationTypes" ADD CONSTRAINT unique_notificationtypelabel UNIQUE (notificationtypelabel);') + + op.execute('ALTER TABLE public."NotificationUserTypes" ADD COLUMN notificationusertypelabel VARCHAR(50);') + op.execute('UPDATE public."NotificationUserTypes" SET notificationusertypelabel = REPLACE(LOWER(name), \' \', \'\');') + op.execute('ALTER TABLE public."NotificationUserTypes" ALTER COLUMN notificationusertypelabel SET NOT NULL;') + op.execute('ALTER TABLE public."NotificationUserTypes" ADD CONSTRAINT unique_notificationusertypelabel UNIQUE (notificationusertypelabel);') + + op.execute('ALTER TABLE public."FOIRequestNotifications" ADD COLUMN notificationtypelabel VARCHAR(50);') + op.execute('UPDATE public."FOIRequestNotifications" AS mr SET notificationtypelabel = st.notificationtypelabel FROM public."NotificationTypes" AS st WHERE mr.notificationtypeid = st.notificationtypeid;') + op.execute('ALTER TABLE public."FOIRequestNotifications" ALTER COLUMN notificationtypelabel SET NOT NULL;') + + op.execute('ALTER TABLE public."FOIRawRequestNotifications" ADD COLUMN notificationtypelabel VARCHAR(50);') + op.execute('UPDATE public."FOIRawRequestNotifications" AS mr SET notificationtypelabel = st.notificationtypelabel FROM public."NotificationTypes" AS st WHERE mr.notificationtypeid = st.notificationtypeid;') + op.execute('ALTER TABLE public."FOIRawRequestNotifications" ALTER COLUMN notificationtypelabel SET NOT NULL;') + + op.execute('ALTER TABLE public."FOIRequestNotificationUsers" ADD COLUMN notificationusertypelabel VARCHAR(50);') + op.execute('UPDATE public."FOIRequestNotificationUsers" AS mr SET notificationusertypelabel = st.notificationusertypelabel FROM public."NotificationUserTypes" AS st WHERE mr.notificationusertypeid = st.notificationusertypeid;') + op.execute('ALTER TABLE public."FOIRequestNotificationUsers" ALTER COLUMN notificationusertypelabel SET NOT NULL;') + + op.execute('ALTER TABLE public."FOIRawRequestNotificationUsers" ADD COLUMN notificationusertypelabel VARCHAR(50);') + op.execute('UPDATE public."FOIRawRequestNotificationUsers" AS mr SET notificationusertypelabel = st.notificationusertypelabel FROM public."NotificationUserTypes" AS st WHERE mr.notificationusertypeid = st.notificationusertypeid;') + op.execute('ALTER TABLE public."FOIRawRequestNotificationUsers" ALTER COLUMN notificationusertypelabel SET NOT NULL;') + + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.execute('ALTER TABLE public."FOIRequestNotifications" drop column notificationtypelabel;') + op.execute('ALTER TABLE public."FOIRequestNotificationUsers" drop column notificationusertypelabel;') + op.execute('ALTER TABLE public."FOIRawRequestNotifications" drop column notificationtypelabel;') + op.execute('ALTER TABLE public."FOIRawRequestNotificationUsers" drop column notificationusertypelabel;') + op.execute('ALTER TABLE public."NotificationTypes" drop column notificationtypelabel;') + op.execute('ALTER TABLE public."NotificationUserTypes" drop column notificationusertypelabel;') + # ### end Alembic commands ### + diff --git a/request-management-api/request_api/models/FOIRawRequestNotificationUsers.py b/request-management-api/request_api/models/FOIRawRequestNotificationUsers.py index 619bdfd9a..8094f76c3 100644 --- a/request-management-api/request_api/models/FOIRawRequestNotificationUsers.py +++ b/request-management-api/request_api/models/FOIRawRequestNotificationUsers.py @@ -32,7 +32,7 @@ class FOIRawRequestNotificationUser(db.Model): updated_at = db.Column(db.DateTime, nullable=True) updatedby = db.Column(db.String(120), unique=False, nullable=True) - notificationusertypeid = db.Column(db.Integer,nullable=False) + notificationusertypelabel = db.Column(db.Integer,nullable=False) @classmethod @@ -53,8 +53,8 @@ def dismissnotificationbyuser(cls, userid): return DefaultMethodResult(True,'Notifications deleted for user',userid) @classmethod - def dismissnotificationbyuserandtype(cls, userid, notificationusertypeid): - db.session.query(FOIRawRequestNotificationUser).filter(FOIRawRequestNotificationUser.userid == userid, FOIRawRequestNotificationUser.notificationusertypeid == notificationusertypeid).update({FOIRawRequestNotificationUser.isdeleted: True, FOIRawRequestNotificationUser.updatedby: userid, + def dismissnotificationbyuserandtype(cls, userid, notificationusertypelabel): + db.session.query(FOIRawRequestNotificationUser).filter(FOIRawRequestNotificationUser.userid == userid, FOIRawRequestNotificationUser.notificationusertypelabel == notificationusertypelabel).update({FOIRawRequestNotificationUser.isdeleted: True, FOIRawRequestNotificationUser.updatedby: userid, FOIRawRequestNotificationUser.updated_at: datetime2.now()}) db.session.commit() return DefaultMethodResult(True,'Notifications deleted for user',userid) @@ -92,12 +92,12 @@ def getnotificationsbyuser(cls, userid): return notifications @classmethod - def getnotificationsbyuserandtype(cls, userid, notificationusertypeid): + def getnotificationsbyuserandtype(cls, userid, notificationusertypelabel): notifications = [] try: sql = """select notificationid, count(1) as relcount from "FOIRawRequestNotificationUsers" frnu - where notificationid in (select notificationid from "FOIRawRequestNotificationUsers" frnu where userid = :userid and notificationusertypeid = :notificationusertypeid) group by notificationid """ - rs = db.session.execute(text(sql), {'userid': userid, 'notificationusertypeid': notificationusertypeid}) + where notificationid in (select notificationid from "FOIRawRequestNotificationUsers" frnu where userid = :userid and notificationusertypelabel = :notificationusertypelabel) group by notificationid """ + rs = db.session.execute(text(sql), {'userid': userid, 'notificationusertypelabel': notificationusertypelabel}) for row in rs: notifications.append({"notificationid": row["notificationid"], "count" : row["relcount"]}) except Exception as ex: @@ -168,7 +168,7 @@ def getbasequery(cls, groups, additionalfilter=None, userid=None, isiaorestricte return basequery.join(subquery_watchby, subquery_watchby.c.requestid == cast(FOIRawRequests.rawrequestid, Integer)) elif(additionalfilter == 'myRequests'): #myrequest - return basequery.filter(or_(FOIRawRequests.assignedto == userid, and_(FOINotifications.userid == userid, FOINotifications.notificationtypeid == 10))) + return basequery.filter(or_(FOIRawRequests.assignedto == userid, and_(FOINotifications.userid == userid, FOINotifications.notificationtypelabel == 10))) else: if(isiaorestrictedfilemanager == True): return basequery.filter(FOIRawRequests.assignedgroup.in_(groups)) @@ -263,4 +263,4 @@ def validatefield(cls, x): class FOIRawRequestNotificationUserSchema(ma.Schema): class Meta: - fields = ('notificationid', 'userid','notificationusertypeid','created_at','createdby','updated_at','updatedby') \ No newline at end of file + fields = ('notificationid', 'userid','notificationusertypelabel','created_at','createdby','updated_at','updatedby') \ No newline at end of file diff --git a/request-management-api/request_api/models/FOIRawRequestNotifications.py b/request-management-api/request_api/models/FOIRawRequestNotifications.py index e0351e90d..248e29c18 100644 --- a/request-management-api/request_api/models/FOIRawRequestNotifications.py +++ b/request-management-api/request_api/models/FOIRawRequestNotifications.py @@ -27,7 +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') @@ -69,11 +69,11 @@ def updatenotification(cls, foinotification, userid): return DefaultMethodResult(True,'No notification found',foinotification['notificationid']) @classmethod - def getnotificationidsbynumberandtype(cls, idnumber, notificationtypeid): + def getnotificationidsbynumberandtype(cls, idnumber, notificationtypelabel): notificationids = [] try: - sql = """select notificationid from "FOIRawRequestNotifications" where idnumber = :idnumber and notificationtypeid= :notificationtypeid """ - rs = db.session.execute(text(sql), {'idnumber': idnumber, 'notificationtypeid': notificationtypeid}) + sql = """select notificationid from "FOIRawRequestNotifications" where idnumber = :idnumber and notificationtypelabel= :notificationtypelabel """ + rs = db.session.execute(text(sql), {'idnumber': idnumber, 'notificationtypelabel': notificationtypelabel}) for row in rs: notificationids.append(row["notificationid"]) except Exception as ex: @@ -99,11 +99,11 @@ def getnotificationidsbynumber(cls, idnumber): return notificationids @classmethod - def getnotificationidsbytype(cls, notificationtypeid): + def getnotificationidsbytype(cls, notificationtypelabel): notificationids = [] try: - sql = """select notificationid from "FOIRawRequestNotifications" where notificationtypeid= :notificationtypeid """ - rs = db.session.execute(text(sql), {'notificationtypeid': notificationtypeid}) + sql = """select notificationid from "FOIRawRequestNotifications" where notificationtypelabel= :notificationtypelabel """ + rs = db.session.execute(text(sql), {'notificationtypelabel': notificationtypelabel}) for row in rs: notificationids.append(row["notificationid"]) except Exception as ex: @@ -115,4 +115,4 @@ def getnotificationidsbytype(cls, notificationtypeid): class FOIRawRequestNotificationSchema(ma.Schema): class Meta: - fields = ('notificationid', 'requestid', 'idnumber','notification', 'notificationtypeid','created_at','createdby','updated_at','updatedby','notificationusers') \ No newline at end of file + fields = ('notificationid', 'requestid', 'idnumber','notification', 'notificationtypelabel','created_at','createdby','updated_at','updatedby','notificationusers') \ No newline at end of file diff --git a/request-management-api/request_api/models/FOIRequestNotificationUsers.py b/request-management-api/request_api/models/FOIRequestNotificationUsers.py index e35dbda75..148d8be9f 100644 --- a/request-management-api/request_api/models/FOIRequestNotificationUsers.py +++ b/request-management-api/request_api/models/FOIRequestNotificationUsers.py @@ -50,7 +50,7 @@ class FOIRequestNotificationUser(db.Model): updated_at = db.Column(db.DateTime, nullable=True) updatedby = db.Column(db.String(120), unique=False, nullable=True) - notificationusertypeid = db.Column(db.Integer,nullable=False) + notificationusertypelabel = db.Column(db.String(100),nullable=False) @classmethod @@ -71,8 +71,8 @@ def dismissnotificationbyuser(cls, userid): return DefaultMethodResult(True,'Notifications deleted for user',userid) @classmethod - def dismissnotificationbyuserandtype(cls, userid, notificationusertypeid): - db.session.query(FOIRequestNotificationUser).filter(FOIRequestNotificationUser.userid == userid, FOIRequestNotificationUser.notificationusertypeid == notificationusertypeid).update({FOIRequestNotificationUser.isdeleted: True, FOIRequestNotificationUser.updatedby: userid, + def dismissnotificationbyuserandtype(cls, userid, notificationusertypelabel): + db.session.query(FOIRequestNotificationUser).filter(FOIRequestNotificationUser.userid == userid, FOIRequestNotificationUser.notificationusertypelabel == notificationusertypelabel).update({FOIRequestNotificationUser.isdeleted: True, FOIRequestNotificationUser.updatedby: userid, FOIRequestNotificationUser.updated_at: datetime2.now()}) db.session.commit() return DefaultMethodResult(True,'Notifications deleted for user',userid) @@ -118,12 +118,12 @@ def getnotificationsbyuser(cls, userid): return notifications @classmethod - def getnotificationsbyuserandtype(cls, userid, notificationusertypeid): + def getnotificationsbyuserandtype(cls, userid, notificationusertypelabel): notifications = [] try: sql = """select notificationid, count(1) as relcount from "FOIRequestNotificationUsers" frnu - where notificationid in (select notificationid from "FOIRequestNotificationUsers" frnu where userid = :userid and notificationusertypeid = :notificationusertypeid) group by notificationid """ - rs = db.session.execute(text(sql), {'userid': userid, 'notificationusertypeid':notificationusertypeid}) + where notificationid in (select notificationid from "FOIRequestNotificationUsers" frnu where userid = :userid and notificationusertypelabel = :notificationusertypelabel) group by notificationid """ + rs = db.session.execute(text(sql), {'userid': userid, 'notificationusertypelabel':notificationusertypelabel}) for row in rs: notifications.append({"notificationid": row["notificationid"], "count" : row["relcount"]}) except Exception as ex: @@ -223,9 +223,9 @@ def geteventsubquery(cls, groups, filterfields, keyword, additionalfilter, useri elif(additionalfilter == 'myRequests'): #myrequest if(requestby == 'IAO'): - dbquery = basequery.filter(or_(and_(FOIRequests.assignedto == userid, ministryfilter),and_(FOINotifications.userid == userid, FOINotifications.notificationtypeid == 10))) + dbquery = basequery.filter(or_(and_(FOIRequests.assignedto == userid, ministryfilter),and_(FOINotifications.userid == userid, FOINotifications.notificationtypelabel == 10))) else: - dbquery = basequery.filter(or_(and_(FOIRequests.assignedministryperson == userid, ministryfilter),and_(FOINotifications.userid == userid, FOINotifications.notificationtypeid == 10))) + dbquery = basequery.filter(or_(and_(FOIRequests.assignedministryperson == userid, ministryfilter),and_(FOINotifications.userid == userid, FOINotifications.notificationtypelabel == 10))) else: if(isiaorestrictedfilemanager == True or isministryrestrictedfilemanager == True): dbquery = basequery @@ -333,4 +333,4 @@ def findfield(cls, x): class FOIRequestNotificationUserSchema(ma.Schema): class Meta: - fields = ('notificationid', 'userid','notificationusertypeid','created_at','createdby','updated_at','updatedby') \ No newline at end of file + fields = ('notificationid', 'userid','notificationusertypelabel','created_at','createdby','updated_at','updatedby') \ No newline at end of file diff --git a/request-management-api/request_api/models/FOIRequestNotifications.py b/request-management-api/request_api/models/FOIRequestNotifications.py index f9b53425a..e4b767c6b 100644 --- a/request-management-api/request_api/models/FOIRequestNotifications.py +++ b/request-management-api/request_api/models/FOIRequestNotifications.py @@ -11,8 +11,10 @@ from sqlalchemy.sql.expression import distinct from sqlalchemy import text import maya - import json +f = open('common/notificationtypes.json', encoding="utf8") +notificationtypes_cache = json.load(f) + class FOIRequestNotification(db.Model): # Name of the table in our database __tablename__ = 'FOIRequestNotifications' @@ -30,7 +32,7 @@ class FOIRequestNotification(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.String(50), nullable=False) notificationusers = db.relationship('FOIRequestNotificationUser', backref='FOIRequestNotifications', lazy='dynamic') @@ -66,9 +68,9 @@ def getconsolidatednotifications(cls, userid, days): notifications = [] try: sql = """select idnumber, axisnumber, notificationid, notification , notificationtype, userid, notificationusertype, created_at, createdby, requesttype, requestid, foirequestid from ( - select frn.idnumber, frn.axisnumber, frn.requestid, frns.notificationuserid as notificationid, 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.notificationtypeid = nty.notificationtypeid inner join "NotificationUserTypes" ntu on frns.notificationusertypeid = ntu.notificationusertypeid where frns.userid=:userid and frn.created_at >= current_date - interval :days day + select frn.idnumber, frn.axisnumber, frn.requestid, frns.notificationuserid as notificationid, 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 inner join "NotificationTypes" nty on frn.notificationtypelabel = nty.notificationtypelabel inner join "NotificationUserTypes" ntu on frns.notificationusertypelabel = ntu.notificationusertypelabel where frns.userid=:userid and frns.isdeleted = false and frn.created_at >= current_date - interval :days day union all - select frn.idnumber, frn.axisnumber, frn.requestid, frns.notificationuserid as notificationid, 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.notificationtypeid = nty.notificationtypeid inner join "NotificationUserTypes" ntu on frns.notificationusertypeid = ntu.notificationusertypeid where frns.userid=:userid and frn.created_at >= current_date - interval :days day + select frn.idnumber, frn.axisnumber, frn.requestid, frns.notificationuserid as notificationid, 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 inner join "NotificationTypes" nty on frn.notificationtypelabel = nty.notificationtypelabel inner join "NotificationUserTypes" ntu on frns.notificationusertypelabel = ntu.notificationusertypelabel where frns.userid=:userid and frns.isdeleted = false and frn.created_at >= current_date - interval :days day ) as notf order by created_at desc""" rs = db.session.execute(text(sql), {'userid': userid, 'days': days}) for row in rs: @@ -87,11 +89,16 @@ 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.notificationtypeid = nty.notificationtypeid inner join "NotificationUserTypes" ntu on frns.notificationusertypeid = ntu.notificationusertypeid where frn.notificationtypeid in (3,9,10) 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.notificationtypeid = nty.notificationtypeid inner join "NotificationUserTypes" ntu on frns.notificationusertypeid = ntu.notificationusertypeid where frn.notificationtypeid in (3,9,10) 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""" - rs = db.session.execute(text(sql), {'commentid': commentid}) + notificationtypelabel = [notificationtypes_cache.newusercomments.notificationtypelabel, + notificationtypes_cache.replyusercomments.notificationtypelabel, + notificationtypes_cache.taggedusercomments.notificationtypelabel, + ] # 3,9,10 + print(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) _createddate = dt @@ -107,10 +114,10 @@ def getcommentnotifications(cls, commentid): def getextensionnotifications(cls, extensionid): notifications = [] try: - sql = sql = """select idnumber, axisnumber, notificationid, notification , notificationtypeid from "FOIRequestNotifications" where notification->>'extensionid' = :extensionid """ + sql = sql = """select idnumber, axisnumber, notificationid, notification , notificationtypelabel from "FOIRequestNotifications" where 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"], "notificationtypeid": row["notificationtypeid"]}) + notifications.append({"idnumber": row["idnumber"], "axisnumber": row["axisnumber"], "notificationid": row["notificationid"], "notification": row["notification"], "notificationtypelabel": row["notificationtypelabel"]}) except Exception as ex: logging.error(ex) raise ex @@ -130,11 +137,11 @@ def dismissnotification(cls, notificationids, userid='system'): raise @classmethod - def getnotificationidsbynumberandtype(cls, idnumber, notificationtypeids): + def getnotificationidsbynumberandtype(cls, idnumber, notificationtypelabels): notificationids = [] try: - sql = """select notificationid from "FOIRequestNotifications" where idnumber = :idnumber and notificationtypeid = ANY(:notificationtypeids) """ - rs = db.session.execute(text(sql), {'idnumber': idnumber, 'notificationtypeids': notificationtypeids}) + sql = """select notificationid from "FOIRequestNotifications" where idnumber = :idnumber and notificationtypelabel = ANY(:notificationtypelabels) """ + rs = db.session.execute(text(sql), {'idnumber': idnumber, 'notificationtypelabels': notificationtypelabels}) for row in rs: notificationids.append(row["notificationid"]) except Exception as ex: @@ -160,9 +167,9 @@ def getnotificationidsbynumber(cls, idnumber): return notificationids @classmethod - def getnotificationidsbytype(cls, notificationtypeid): - sql = """select notificationid from "FOIRequestNotifications" where notificationtypeid= :notificationtypeid """ - rs = db.session.execute(text(sql), {'notificationtypeid': notificationtypeid}) + def getnotificationidsbytype(cls, notificationtypelabel): + sql = """select notificationid from "FOIRequestNotifications" where notificationtypelabel= :notificationtypelabel """ + rs = db.session.execute(text(sql), {'notificationtypelabel': notificationtypelabel}) notificationids = [] for row in rs: notificationids.append(row["notificationid"]) @@ -170,7 +177,7 @@ def getnotificationidsbytype(cls, notificationtypeid): @classmethod def getextensionnotificationidsbyministry(cls, ministryid): - sql = """select notificationid from "FOIRequestNotifications" where requestid = :requestid and notificationtypeid = 4 """ + sql = """select notificationid from "FOIRequestNotifications" where requestid = :requestid and notificationtypelabel = 4 """ rs = db.session.execute(text(sql), {'requestid': ministryid}) notificationids = [] for row in rs: @@ -179,4 +186,4 @@ def getextensionnotificationidsbyministry(cls, ministryid): class FOIRequestNotificationSchema(ma.Schema): class Meta: - fields = ('notificationid', 'ministryrequestid', 'notification', 'notificationtypeid','created_at','createdby','updated_at','updatedby') \ No newline at end of file + fields = ('notificationid', 'ministryrequestid', 'notification', 'notificationtypeid', 'notificationtypelabel','created_at','createdby','updated_at','updatedby') \ No newline at end of file diff --git a/request-management-api/request_api/models/NotificationTypes.py b/request-management-api/request_api/models/NotificationTypes.py index a3743612a..71be7a7d3 100644 --- a/request-management-api/request_api/models/NotificationTypes.py +++ b/request-management-api/request_api/models/NotificationTypes.py @@ -11,14 +11,23 @@ class NotificationType(db.Model): name = db.Column(db.String(100), unique=False, nullable=False) description = db.Column(db.String(255), unique=False, nullable=False) isactive = db.Column(db.Boolean, unique=False, nullable=False) + notificationtypelabel = db.Column(db.String(100), unique=True, nullable=False) @classmethod def getnotificationtypes(cls): type_schema = NotificationTypeSchema(many=True) query = db.session.query(NotificationType).filter_by(isactive=True).all() return type_schema.dump(query) + + # create a class method that returns the notification type id + @classmethod + def getnotificationtypeid(cls, notificationtype): + type_schema = NotificationTypeSchema(many=False) + query = db.session.query(NotificationType).filter_by(name=notificationtype, isactive=True).first() + return type_schema.dump(query) if query is not None else None class NotificationTypeSchema(ma.Schema): class Meta: - fields = ('notificationtypeid', 'name', 'description','isactive') \ No newline at end of file + fields = ('notificationtypeid', 'name', 'description','isactive', 'notificationtypelabel') + diff --git a/request-management-api/request_api/models/NotificationUserTypes.py b/request-management-api/request_api/models/NotificationUserTypes.py index 054b4c213..49cadfaaa 100644 --- a/request-management-api/request_api/models/NotificationUserTypes.py +++ b/request-management-api/request_api/models/NotificationUserTypes.py @@ -11,14 +11,22 @@ class NotificationUserType(db.Model): name = db.Column(db.String(100), unique=False, nullable=False) description = db.Column(db.String(255), unique=False, nullable=False) isactive = db.Column(db.Boolean, unique=False, nullable=False) + notificationusertypelabel = db.Column(db.String(100), unique=True, nullable=False) @classmethod def getnotificationusertypes(cls): usertype_schema = NotificationUserTypeSchema(many=True) query = db.session.query(NotificationUserType).filter_by(isactive=True).all() return usertype_schema.dump(query) + + # create a class method that returns the notification type id + @classmethod + def getnotificationusertypesid(cls, notificationusertype): + type_schema = NotificationUserTypeSchema(many=False) + query = db.session.query(NotificationUserType).filter_by(name=notificationusertype, isactive=True).first() + return type_schema.dump(query) if query is not None else None class NotificationUserTypeSchema(ma.Schema): class Meta: - fields = ('notificationusertypeid', 'name', 'description','isactive') \ No newline at end of file + fields = ('notificationusertypeid', 'notificationusertypelabel', 'name', 'description','isactive') \ No newline at end of file diff --git a/request-management-api/request_api/models/views/FOINotifications.py b/request-management-api/request_api/models/views/FOINotifications.py index ab6b9e214..dc14ffe7b 100644 --- a/request-management-api/request_api/models/views/FOINotifications.py +++ b/request-management-api/request_api/models/views/FOINotifications.py @@ -17,4 +17,5 @@ class FOINotifications(db.Model): userformatted = db.Column(db.Text) creatorformatted = db.Column(db.Text) notificationtype = db.Column(db.String(500)) + notificationtypelabel = db.Column(db.String(500)) diff --git a/request-management-api/request_api/services/notifications/notificationconfig.py b/request-management-api/request_api/services/notifications/notificationconfig.py index 44175ed20..e00fe0f62 100644 --- a/request-management-api/request_api/services/notifications/notificationconfig.py +++ b/request-management-api/request_api/services/notifications/notificationconfig.py @@ -3,54 +3,26 @@ from re import VERBOSE import json import os +from request_api.models.NotificationTypes import NotificationType +from request_api.models.NotificationUserTypes import NotificationUserType class notificationconfig: """ Notfication config """ - + def getnotificationtypeid(self, notificationtype): - if notificationtype == "State": - return 1 - elif notificationtype == "Extension": - return 4 - elif "IAO Assignment" in notificationtype: - return 5 - elif "Ministry Assignment" in notificationtype: - return 6 - elif notificationtype == "CFR Due Reminder": - return 7 - elif notificationtype == "Legislative Due Reminder": - return 8 - elif notificationtype == "New User Comments": - return 3 - elif notificationtype == "Reply User Comments": - return 9 - elif notificationtype == "Tagged User Comments": - return 10 - elif notificationtype == "CFR Fee Form": - return 11 - elif notificationtype == "Group Members": - return 12 - elif notificationtype == "Division Due Reminder": - return 13 - elif notificationtype == "Watcher": - return 14 - elif notificationtype == "User Assignment Removal": - return 15 - elif notificationtype == "Email Failure": - return 16 - elif notificationtype == "Payment": - return 17 - elif notificationtype == "Section 5 Pending Reminder": - return 20 - return 0 - + id = NotificationType().getnotificationtypeid(notificationtype) + if id is not None: + return id['notificationtypelabel'] + return 0 + def getnotificationusertypeid(self, notificationusertype): - if notificationusertype.lower() == "watcher": - return 1 - elif notificationusertype.lower() == "assignee" or "comment" or "group members" in notificationusertype.lower(): - return 2 + print(notificationusertype) + id = NotificationUserType().getnotificationusertypesid(notificationusertype) + print(id) + if id is not None: + return id['notificationusertypelabel'] return 0 def getnotificationdays(self): diff --git a/request-management-api/request_api/services/notifications/notificationuser.py b/request-management-api/request_api/services/notifications/notificationuser.py index 2b5a104cf..b7c234ac8 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 = [] - notificationtypeid = notificationconfig().getnotificationusertypeid("Assignee") + notificationtypelabel = notificationconfig().getnotificationusertypeid("Assignee") if notificationtype == 'User Assignment Removal': - notificationusers.append({"userid": requestjson['userid'], "usertype":notificationtypeid}) + notificationusers.append({"userid": requestjson['userid'], "usertype":notificationtypelabel}) 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":notificationtypeid}) + notificationusers.append({"userid":foirequest["assignedministryperson"], "usertype":notificationtypelabel}) 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":notificationtypeid}) + notificationusers.append({"userid":foirequest["assignedto"], "usertype":notificationtypelabel}) return notificationusers def __isministryonly(self, notificationtype): @@ -123,11 +123,11 @@ def __preparetaggeduser(self, data): def __getgroupmembers(self,groupid): notificationusers = [] - notificationtypeid = notificationconfig().getnotificationusertypeid("Group Members") + notificationtypelabel = notificationconfig().getnotificationusertypeid("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":notificationtypeid}) + notificationusers.append({"userid":user["username"], "usertype":notificationtypelabel}) 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 036a4ae60..08d4f8c76 100644 --- a/request-management-api/request_api/services/notificationservice.py +++ b/request-management-api/request_api/services/notificationservice.py @@ -93,7 +93,7 @@ def dismissnotificationbyid(self, requesttype, notificationids): return self.__deletenotificationids(requesttype, notificationids) def dismissremindernotification(self, requesttype, notificationtype): - notificationid = notificationconfig().getnotificationtypeid(notificationtype) + notificationid = notificationconfig().getnotificationtypelabel(notificationtype) if requesttype == "ministryrequest": _ids = FOIRequestNotification.getnotificationidsbytype(notificationid) else: @@ -101,13 +101,13 @@ def dismissremindernotification(self, requesttype, notificationtype): self.__deletenotificationids(requesttype, _ids) def dismissnotifications_by_requestid_type_userid(self, requestid, requesttype, notificationtype, userid): - notificationtypeids = self.__getcleanupnotificationids(notificationtype) + notificationtypelabels = self.__getcleanupnotificationids(notificationtype) foirequest = self.getrequest(requestid, requesttype) if requesttype == "ministryrequest": idnumber = foirequest["filenumber"] - _ids = FOIRequestNotification.getnotificationidsbynumberandtype(idnumber, notificationtypeids) + _ids = FOIRequestNotification.getnotificationidsbynumberandtype(idnumber, notificationtypelabels) else: - _ids = FOIRawRequestNotification.getnotificationidsbynumberandtype('U-00' + str(foirequest['requestid']), notificationtypeids[0]) + _ids = FOIRawRequestNotification.getnotificationidsbynumberandtype('U-00' + str(foirequest['requestid']), notificationtypelabels[0]) self.__deletenotificationbyuserandid(requesttype, _ids, userid) def __createnotification(self, message, requestid, requesttype, notificationtype, userid, foirequest, requestjson=None): @@ -134,22 +134,22 @@ def dismissnotificationsbyrequestid(self,requestid, requesttype): FOIRawRequestNotification.dismissnotification(_ids) def __cleanupnotifications(self, requesttype, notificationtype, foirequest): - notificationtypeids = self.__getcleanupnotificationids(notificationtype) + notificationtypelabels = self.__getcleanupnotificationids(notificationtype) if requesttype == "ministryrequest": idnumber = foirequest["filenumber"] - _ids = FOIRequestNotification.getnotificationidsbynumberandtype(idnumber, notificationtypeids) + _ids = FOIRequestNotification.getnotificationidsbynumberandtype(idnumber, notificationtypelabels) else: - _ids = FOIRawRequestNotification.getnotificationidsbynumberandtype('U-00' + str(foirequest['requestid']), notificationtypeids[0]) + _ids = FOIRawRequestNotification.getnotificationidsbynumberandtype('U-00' + str(foirequest['requestid']), notificationtypelabels[0]) self.__deletenotificationids(requesttype, _ids) def __getcleanupnotificationids(self, notificationtype): - notificationtypeids = [] - notificationid = notificationconfig().getnotificationtypeid(notificationtype) - notificationtypeids.append(notificationid) + notificationtypelabels = [] + notificationid = notificationconfig().getnotificationtypelabel(notificationtype) + notificationtypelabels.append(notificationid) if notificationtype == "State" or notificationtype.endswith("Assignment"): - notificationtypeids.append(notificationconfig().getnotificationtypeid("Group Members")) - return notificationtypeids + notificationtypelabels.append(notificationconfig().getnotificationtypelabel("Group Members")) + return notificationtypelabels def __deletenotificationids(self, requesttype, notificationids): @@ -191,7 +191,7 @@ def __dismissnotificationbyuser(self, userid): return DefaultMethodResult(False,'Unable to delete the notifications',userid) def __dismissnotificationbytype(self, userid, type): - typeid = notificationconfig().getnotificationusertypeid(type) + typeid = notificationconfig().getnotificationusertypelabel(type) requestnotificationids = self.__getdismissparentidsbyuserandtype("ministryrequest", userid, typeid) requestnotification = FOIRequestNotificationUser.dismissnotificationbyuserandtype(userid, typeid) rawnotificationids = self.__getdismissparentidsbyuserandtype("rawrequest", userid, typeid) @@ -273,7 +273,7 @@ def __preparenotification(self, message, requesttype, notificationtype, userid, notification.idnumber ='U-00' + str(foirequest['requestid']) mutenotification = False - notification.notificationtypeid = notificationconfig().getnotificationtypeid(notificationtype) + notification.notificationtypelabel = notificationconfig().getnotificationtypelabel(notificationtype) notification.axisnumber = foirequest["axisrequestid"] notification.version = foirequest["version"] notification.createdby = userid @@ -296,8 +296,7 @@ def __preparenotificationuser(self, requesttype, notificationuser, userid, mute= user.isdeleted = False else: user = FOIRawRequestNotificationUser() - user.isdeleted = False - user.notificationusertypeid = notificationuser["usertype"] + user.notificationusertypelabel = notificationuser["usertype"] user.userid = notificationuser["userid"] user.createdby = userid return user From 28320d8dfc654ae26da6f620d0ca6f08b40d4d24 Mon Sep 17 00:00:00 2001 From: divyav-aot Date: Fri, 24 Nov 2023 15:29:18 -0500 Subject: [PATCH 13/22] statusEnum and migrationscript changes --- .../src/constants/FOI/statusEnum.js | 54 ++++-- .../versions/d185518c3661_ state_label.py | 180 ++++++++++++++++++ 2 files changed, 213 insertions(+), 21 deletions(-) diff --git a/forms-flow-web/src/constants/FOI/statusEnum.js b/forms-flow-web/src/constants/FOI/statusEnum.js index aae8ef2ae..b40603da1 100644 --- a/forms-flow-web/src/constants/FOI/statusEnum.js +++ b/forms-flow-web/src/constants/FOI/statusEnum.js @@ -188,27 +188,39 @@ const MinistryStateList = Object.freeze({ // This corresponds to rows in the FOIRequestStatuses table on the backend const StateEnum = Object.freeze({ - open: { name: "Open", id: 1 }, - callforrecords: { name: "Call For Records", id: 2 }, - callforrecordsoverdue: { name: "Call For Records Overdue", id: -100 }, - closed: { name: "Closed", id: 3 }, - redirect: { name: "Redirect", id: 4 }, - unopened: { name: "Unopened", id: 5 }, - intakeinprogress: { name: "Intake in Progress", id: 6 }, - review: { name: "Records Review", id: 7 }, - feeassessed: { name: "Fee Estimate", id: 8 }, - consult: { name: "Consult", id: 9 }, - signoff: { name: "Ministry Sign Off", id: 10 }, - onhold: { name: "On Hold", id: 11 }, - deduplication: { name: "Deduplication", id: 12 }, - harms: { name: "Harms Assessment", id: 13 }, - response: { name: "Response", id: 14 }, - archived: { name: "Archived", id: 15 }, - peerreview: { name: "Peer Review", id: 16 }, - tagging: { name: "Tagging", id: 17 }, - readytoscan: { name: "Ready to Scan", id: 18 }, - appfeeowing: { name: "App Fee Owing", id: 19 }, - section5pending: { name: "Section 5 Pending", id: 20 }, + open: { name: "Open", id: 1, label: "open" }, + callforrecords: { name: "Call For Records", id: 2, label: "callforrecords" }, + callforrecordsoverdue: { + name: "Call For Records Overdue", + id: -100, + label: "callforrecordsoverdue", + }, + closed: { name: "Closed", id: 3, label: "closed" }, + redirect: { name: "Redirect", id: 4, label: "redirect" }, + unopened: { name: "Unopened", id: 5, label: "unopened" }, + intakeinprogress: { + name: "Intake in Progress", + id: 6, + label: "intakeinprogress", + }, + review: { name: "Records Review", id: 7, label: "recordsreview" }, + feeassessed: { name: "Fee Estimate", id: 8, label: "feeestimate" }, + consult: { name: "Consult", id: 9, label: "consult" }, + signoff: { name: "Ministry Sign Off", id: 10, label: "ministrysignoff" }, + onhold: { name: "On Hold", id: 11, label: "onhold" }, + deduplication: { name: "Deduplication", id: 12, label: "deduplication" }, + harms: { name: "Harms Assessment", id: 13, label: "harmsassessment" }, + response: { name: "Response", id: 14, label: "response" }, + archived: { name: "Archived", id: 15, label: "archived" }, + peerreview: { name: "Peer Review", id: 16, label: "peerreview" }, + tagging: { name: "Tagging", id: 17, label: "tagging" }, + readytoscan: { name: "Ready to Scan", id: 18, label: "readytoscan" }, + appfeeowing: { name: "App Fee Owing", id: 19, label: "appfeeowing" }, + section5pending: { + name: "Section 5 Pending", + id: 20, + label: "section5pending", + }, }); const StateTransitionCategories = Object.freeze({ diff --git a/request-management-api/migrations/versions/d185518c3661_ state_label.py b/request-management-api/migrations/versions/d185518c3661_ state_label.py index 36814855b..9b1dd55ae 100644 --- a/request-management-api/migrations/versions/d185518c3661_ state_label.py +++ b/request-management-api/migrations/versions/d185518c3661_ state_label.py @@ -27,14 +27,103 @@ def upgrade(): op.execute('ALTER TABLE public."FOIMinistryRequests" ADD COLUMN requeststatuslabel VARCHAR(50);') op.execute('UPDATE public."FOIMinistryRequests" AS mr SET requeststatuslabel = st.statuslabel FROM public."FOIRequestStatuses" AS st WHERE mr.requeststatusid = st.requeststatusid;') op.execute('ALTER TABLE public."FOIMinistryRequests" ALTER COLUMN requeststatuslabel SET NOT NULL;') + op.execute('DROP INDEX "FOIMinistryRequests_event";') + op.execute('CREATE INDEX "FOIMinistryRequests_event" ON "FOIMinistryRequests"(axisrequestid, assignedto, assignedgroup, assignedministryperson, assignedministrygroup, requeststatusid, requeststatuslabel);') op.execute('ALTER TABLE public."FOIRawRequests" ADD COLUMN requeststatuslabel VARCHAR(50);') op.execute('UPDATE public."FOIRawRequests" SET requeststatuslabel = REPLACE(LOWER(status), \' \', \'\');') op.execute('ALTER TABLE public."FOIRawRequests" ALTER COLUMN requeststatuslabel SET NOT NULL;') + op.execute('DROP INDEX "FOIRawRequests_event";') + op.execute('CREATE INDEX "FOIRawRequests_event" ON "FOIRawRequests" (axisrequestid, assignedto, assignedgroup, status, requeststatuslabel);') op.execute('ALTER TABLE public."FOIRequestTeams" ADD COLUMN requeststatuslabel VARCHAR(50);') op.execute('UPDATE public."FOIRequestTeams" AS rt SET requeststatuslabel = st.statuslabel FROM public."FOIRequestStatuses" AS st WHERE rt.requeststatusid = st.requeststatusid;') op.execute('ALTER TABLE public."FOIRequestTeams" ALTER COLUMN requeststatuslabel SET NOT NULL;') + + + op.execute(""" +CREATE OR REPLACE VIEW public."v_FOIRequests" +AS SELECT DISTINCT ON (fr.foiministryrequestid) fr.foiministryrequestid, + fr.version, + fr.axisrequestid, + fr.foirequest_id, + NULL::text AS rawrequestid, + fr.assignedto, + fr.assignedgroup, + fr.assignedministryperson, + fr.assignedministrygroup, + CASE + WHEN asg.lastname IS NOT NULL AND asg.firstname IS NOT NULL THEN ((asg.lastname::text || ', '::text) || asg.firstname::text)::character varying + WHEN asg.lastname IS NOT NULL AND asg.firstname IS NULL THEN asg.lastname + WHEN asg.lastname IS NULL AND asg.firstname IS NOT NULL THEN asg.firstname + ELSE coalesce(fr.assignedto, fr.assignedgroup) + END AS assignedtoformatted, + CASE + WHEN msg.lastname IS NOT NULL AND msg.firstname IS NOT NULL THEN ((msg.lastname::text || ', '::text) || msg.firstname::text)::character varying + WHEN msg.lastname IS NOT NULL AND msg.firstname IS NULL THEN msg.lastname + WHEN msg.lastname IS NULL AND msg.firstname IS NOT NULL THEN msg.firstname + ELSE coalesce(fr.assignedministryperson, fr.assignedministrygroup) + END AS ministryassignedtoformatted, + fr.requeststatusid, + fs2.name AS status, + fr.description, to_char(fr.created_at,'YYYYMMDDHH24MMSSMSUS') crtid, + fr.requeststatuslabel AS requeststatuslabel + FROM "FOIMinistryRequests" fr + JOIN "FOIRequestStatuses" fs2 ON fr.requeststatusid = fs2.requeststatusid + LEFT JOIN "FOIAssignees" asg ON fr.assignedto::text = asg.username::text + LEFT JOIN "FOIAssignees" msg ON fr.assignedministryperson::text = msg.username::text + ORDER BY fr.foiministryrequestid, fr.version DESC, fr.axisrequestid; +""") + op.execute(""" +CREATE OR REPLACE VIEW public."v_FOIRawRequests" +AS SELECT tmp.requestid::text AS rawrequestid, + tmp.axisrequestid, + tmp.foirequest_id, + tmp.ministryrequestid, + tmp.assignedto, + tmp.assignedgroup, + tmp.assignedministryperson, + tmp.assignedministrygroup, + tmp.assignedtoformatted, + tmp.ministryassignedtoformatted, + tmp.status, + tmp.description, + tmp.isiaorestricted, + tmp.crtid + FROM ( SELECT DISTINCT ON (fr.requestid) fr.requestid, + fr.version, + CASE + WHEN fr.axisrequestid IS NULL THEN ('U-00'::text || fr.requestid)::character varying + ELSE fr.axisrequestid + END AS axisrequestid, + NULL::integer AS foirequest_id, + NULL::integer AS ministryrequestid, + fr.assignedto, + fr.assignedgroup, + NULL::text AS assignedministryperson, + NULL::text AS assignedministrygroup, + CASE + WHEN asg.lastname IS NOT NULL AND asg.firstname IS NOT NULL THEN ((asg.lastname::text || ', '::text) || asg.firstname::text)::character varying + WHEN asg.lastname IS NOT NULL AND asg.firstname IS NULL THEN asg.lastname + WHEN asg.lastname IS NULL AND asg.firstname IS NOT NULL THEN asg.firstname + ELSE coalesce(fr.assignedto, fr.assignedgroup) + END AS assignedtoformatted, + NULL::text AS ministryassignedtoformatted, + fr.status, + CASE + WHEN fr.status::text = 'Unopened'::text THEN (fr.requestrawdata -> 'descriptionTimeframe'::text) ->> 'description'::text + ELSE fr.requestrawdata ->> 'description'::text + END AS description, + fr.isiaorestricted, to_char(fr.created_at,'YYYYMMDDHH24MMSSMSUS') crtid + FROM "FOIRawRequests" fr + LEFT JOIN "FOIAssignees" asg ON fr.assignedto::text = asg.username::text + WHERE NOT (fr.axisrequestid::text IN ( SELECT "v_FOIRequests".axisrequestid + FROM "v_FOIRequests" + WHERE "v_FOIRequests".requeststatuslabel = 'closed')) + ORDER BY fr.requestid, fr.version DESC, fr.axisrequestid) tmp + WHERE tmp.status::text <> ALL (ARRAY['Archived'::character varying, 'Unopened'::character varying, 'Closed'::character varying]::text[]); +""") + # ### end Alembic commands ### @@ -44,4 +133,95 @@ def downgrade(): op.execute('ALTER TABLE public."FOIMinistryRequests" drop column requeststatuslabel;') op.execute('ALTER TABLE public."FOIRawRequests" drop column requeststatuslabel;') op.execute('ALTER TABLE public."FOIRequestTeams" drop column requeststatuslabel;') + + op.execute('DROP INDEX "FOIMinistryRequests_event";') + op.execute('CREATE INDEX "FOIMinistryRequests_event" ON "FOIMinistryRequests"(axisrequestid, assignedto, assignedgroup, assignedministryperson, assignedministrygroup, requeststatusid);') + + op.execute('DROP INDEX "FOIRawRequests_event";') + op.execute('CREATE INDEX "FOIRawRequests_event" ON "FOIRawRequests" (axisrequestid, assignedto, assignedgroup, status);') + + op.execute('DROP VIEW public."v_FOIRawRequests";') + op.execute('DROP VIEW public."v_FOIRequests";') + + op.execute(""" +CREATE OR REPLACE VIEW public."v_FOIRequests" +AS SELECT DISTINCT ON (fr.foiministryrequestid) fr.foiministryrequestid, + fr.version, + fr.axisrequestid, + fr.foirequest_id, + NULL::text AS rawrequestid, + fr.assignedto, + fr.assignedgroup, + fr.assignedministryperson, + fr.assignedministrygroup, + CASE + WHEN asg.lastname IS NOT NULL AND asg.firstname IS NOT NULL THEN ((asg.lastname::text || ', '::text) || asg.firstname::text)::character varying + WHEN asg.lastname IS NOT NULL AND asg.firstname IS NULL THEN asg.lastname + WHEN asg.lastname IS NULL AND asg.firstname IS NOT NULL THEN asg.firstname + ELSE coalesce(fr.assignedto, fr.assignedgroup) + END AS assignedtoformatted, + CASE + WHEN msg.lastname IS NOT NULL AND msg.firstname IS NOT NULL THEN ((msg.lastname::text || ', '::text) || msg.firstname::text)::character varying + WHEN msg.lastname IS NOT NULL AND msg.firstname IS NULL THEN msg.lastname + WHEN msg.lastname IS NULL AND msg.firstname IS NOT NULL THEN msg.firstname + ELSE coalesce(fr.assignedministryperson, fr.assignedministrygroup) + END AS ministryassignedtoformatted, + fr.requeststatusid, + fs2.name AS status, + fr.description, to_char(fr.created_at,'YYYYMMDDHH24MMSSMSUS') crtid + FROM "FOIMinistryRequests" fr + JOIN "FOIRequestStatuses" fs2 ON fr.requeststatusid = fs2.requeststatusid + LEFT JOIN "FOIAssignees" asg ON fr.assignedto::text = asg.username::text + LEFT JOIN "FOIAssignees" msg ON fr.assignedministryperson::text = msg.username::text + ORDER BY fr.foiministryrequestid, fr.version DESC, fr.axisrequestid; +""") + op.execute(""" +CREATE OR REPLACE VIEW public."v_FOIRawRequests" +AS SELECT tmp.requestid::text AS rawrequestid, + tmp.axisrequestid, + tmp.foirequest_id, + tmp.ministryrequestid, + tmp.assignedto, + tmp.assignedgroup, + tmp.assignedministryperson, + tmp.assignedministrygroup, + tmp.assignedtoformatted, + tmp.ministryassignedtoformatted, + tmp.status, + tmp.description, + tmp.isiaorestricted, + tmp.crtid + FROM ( SELECT DISTINCT ON (fr.requestid) fr.requestid, + fr.version, + CASE + WHEN fr.axisrequestid IS NULL THEN ('U-00'::text || fr.requestid)::character varying + ELSE fr.axisrequestid + END AS axisrequestid, + NULL::integer AS foirequest_id, + NULL::integer AS ministryrequestid, + fr.assignedto, + fr.assignedgroup, + NULL::text AS assignedministryperson, + NULL::text AS assignedministrygroup, + CASE + WHEN asg.lastname IS NOT NULL AND asg.firstname IS NOT NULL THEN ((asg.lastname::text || ', '::text) || asg.firstname::text)::character varying + WHEN asg.lastname IS NOT NULL AND asg.firstname IS NULL THEN asg.lastname + WHEN asg.lastname IS NULL AND asg.firstname IS NOT NULL THEN asg.firstname + ELSE coalesce(fr.assignedto, fr.assignedgroup) + END AS assignedtoformatted, + NULL::text AS ministryassignedtoformatted, + fr.status, + CASE + WHEN fr.status::text = 'Unopened'::text THEN (fr.requestrawdata -> 'descriptionTimeframe'::text) ->> 'description'::text + ELSE fr.requestrawdata ->> 'description'::text + END AS description, + fr.isiaorestricted, to_char(fr.created_at,'YYYYMMDDHH24MMSSMSUS') crtid + FROM "FOIRawRequests" fr + LEFT JOIN "FOIAssignees" asg ON fr.assignedto::text = asg.username::text + WHERE NOT (fr.axisrequestid::text IN ( SELECT "v_FOIRequests".axisrequestid + FROM "v_FOIRequests" + WHERE "v_FOIRequests".requeststatusid = 3)) + ORDER BY fr.requestid, fr.version DESC, fr.axisrequestid) tmp + WHERE tmp.status::text <> ALL (ARRAY['Archived'::character varying, 'Unopened'::character varying, 'Closed'::character varying]::text[]); +""") # ### end Alembic commands ### From 939fd21b251032999441f26148e05cf4eb6fdc0c Mon Sep 17 00:00:00 2001 From: divyav-aot Date: Mon, 27 Nov 2023 11:49:30 -0500 Subject: [PATCH 14/22] stateEnum changes to FE and BE --- .../IAO/AdvancedSearch/SearchComponent.js | 35 ++++----- .../AdvancedSearch/SearchComponent.js | 27 ++++--- .../FOIRequest/AxisDetails/AxisSyncModal.js | 5 +- .../FOI/FOIRequest/BottomButtonGroup/index.js | 14 ++-- .../components/FOI/FOIRequest/FOIRequest.js | 4 +- .../MinistryReview/BottomButtonGroup.js | 22 +++--- .../FOI/FOIRequest/RequestDetails.js | 2 +- .../src/components/FOI/FOIRequest/utils.js | 6 +- .../ConfirmationModal/index.js | 24 +++--- .../ConfirmationModal/util.js | 6 +- .../src/constants/FOI/statusEnum.js | 54 +++++-------- .../request_api/models/FOIMinistryRequests.py | 77 ++++++++++--------- .../request_api/models/FOIRawRequests.py | 55 ++++++------- .../models/FOIRequestNotificationUsers.py | 6 +- .../request_api/models/FOIRequestStatus.py | 9 ++- .../request_api/models/FOIRequestTeams.py | 16 ++-- .../request_api/models/views/FOIRequests.py | 1 + .../request_api/resources/foirequest.py | 3 +- .../request_api/resources/request.py | 9 ++- .../request_api/schemas/foirequestwrapper.py | 2 + .../request_api/services/events/state.py | 27 ++++--- .../foirequest/requestservicebuilder.py | 25 ++++-- .../foirequest/requestserviceconfigurator.py | 4 +- .../foirequest/requestservicecreate.py | 9 ++- .../foirequest/requestservicegetter.py | 9 ++- .../requestserviceministrybuilder.py | 16 +++- .../foirequest/requestserviceupdate.py | 2 +- .../rawrequest/rawrequestservicegetter.py | 16 ++-- .../request_api/services/rawrequestservice.py | 15 ++-- .../request_api/services/requestservice.py | 20 ++--- .../request_api/services/workflowservice.py | 2 +- .../request_api/utils/enums.py | 11 ++- 32 files changed, 287 insertions(+), 246 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..25c7e352b 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 @@ -128,15 +128,14 @@ const AdvancedSearch = ({ userDetail }) => { }); const intitialRequestState = { - [StateEnum.unopened.id]: false, - [StateEnum.open.id]: false, - [StateEnum.callforrecords.id]: false, - [StateEnum.review.id]: false, - [StateEnum.signoff.id]: false, - [StateEnum.closed.id]: false, - [StateEnum.callforrecordsoverdue.id]: false + [StateEnum.unopened.label]: false, + [StateEnum.open.label]: false, + [StateEnum.callforrecords.label]: false, + [StateEnum.review.label]: false, + [StateEnum.signoff.label]: false, + [StateEnum.closed.label]: false, + [StateEnum.callforrecordsoverdue.label]: false }; - const [requestState, setRequestState] = useState(() => { if (Object.keys(advancedSearchParams).length > 0 && advancedSearchParams.requestState.length > 0) { let savedRequestState = {...intitialRequestState} @@ -579,9 +578,9 @@ const AdvancedSearch = ({ userDetail }) => { } @@ -593,9 +592,9 @@ const AdvancedSearch = ({ userDetail }) => { } @@ -607,9 +606,9 @@ const AdvancedSearch = ({ userDetail }) => { } @@ -621,9 +620,9 @@ const AdvancedSearch = ({ userDetail }) => { } @@ -635,9 +634,9 @@ const AdvancedSearch = ({ userDetail }) => { } 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..83325ebde 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 @@ -127,13 +127,12 @@ const AdvancedSearch = ({ userDetail }) => { }); const intitialRequestState = { - [StateEnum.callforrecords.id]: false, - [StateEnum.review.id]: false, - [StateEnum.signoff.id]: false, - [StateEnum.closed.id]: false, - [StateEnum.callforrecordsoverdue.id]: false + [StateEnum.callforrecords.label]: false, + [StateEnum.review.label]: false, + [StateEnum.signoff.label]: false, + [StateEnum.closed.label]: false, + [StateEnum.callforrecordsoverdue.label]: false }; - const [requestState, setRequestState] = useState(() => { if (Object.keys(advancedSearchParams).length > 0 && advancedSearchParams.requestState.length > 0) { let savedRequestState = {...intitialRequestState} @@ -592,9 +591,9 @@ const AdvancedSearch = ({ userDetail }) => { } @@ -606,9 +605,9 @@ const AdvancedSearch = ({ userDetail }) => { } @@ -620,9 +619,9 @@ const AdvancedSearch = ({ userDetail }) => { } @@ -634,9 +633,9 @@ const AdvancedSearch = ({ userDetail }) => { } diff --git a/forms-flow-web/src/components/FOI/FOIRequest/AxisDetails/AxisSyncModal.js b/forms-flow-web/src/components/FOI/FOIRequest/AxisDetails/AxisSyncModal.js index 57b1ef567..df288a2a5 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/AxisDetails/AxisSyncModal.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/AxisDetails/AxisSyncModal.js @@ -298,8 +298,9 @@ const AxisSyncModal = ({ axisSyncModalOpen, setAxisSyncModalOpen, saveRequestObj const saveAxisData = async () => { - if (urlIndexCreateRequest > -1) - updatedSaveReqObj.requeststatusid = StateEnum.intakeinprogress.id; + if (urlIndexCreateRequest > -1) { + updatedSaveReqObj.requeststatuslabel = StateEnum.intakeinprogress.label; + } dispatch(saveRequestDetails(updatedSaveReqObj, urlIndexCreateRequest,requestId,ministryId, (err, res) => { if (!err) { 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..e7bb8b0b5 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/BottomButtonGroup/index.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/BottomButtonGroup/index.js @@ -115,7 +115,7 @@ const BottomButtonGroup = React.memo( const saveRequest = async (setLoader = false) => { if (urlIndexCreateRequest > -1) { - saveRequestObject.requeststatusid = StateEnum.intakeinprogress.id; + saveRequestObject.requeststatuslabel = StateEnum.intakeinprogress.label; setIsAddRequest(false); } dispatch(setFOILoader(setLoader)) @@ -176,7 +176,7 @@ const BottomButtonGroup = React.memo( if ( currentSelectedStatus && currentSelectedStatus !== StateEnum.open.name && - saveRequestObject.requeststatusid && + saveRequestObject.requeststatuslabel && saveRequestObject.currentState ) { //scanning team - MSD/CFD personal @@ -200,7 +200,7 @@ const BottomButtonGroup = React.memo( } saveRequestModal(); } else { - saveRequestObject.requeststatusid = StateEnum.open.id; + saveRequestObject.requeststatuslabel = StateEnum.open.label; if (currentSelectedStatus === StateEnum.open.name && ministryId) { saveRequestModal(); } @@ -231,7 +231,7 @@ const BottomButtonGroup = React.memo( saveRequestObject.id = saveRequestObject.id ? saveRequestObject.id : requestId; - saveRequestObject.requeststatusid = 1; + saveRequestObject.requeststatuslabel = StateEnum.open.label; setOpenModal(true); }; @@ -292,14 +292,14 @@ const BottomButtonGroup = React.memo( if (currentSelectedStatus) { switch (currentSelectedStatus) { case StateEnum.closed.name: - saveRequestObject.requeststatusid = StateEnum.closed.id; + saveRequestObject.requeststatuslabel = StateEnum.closed.label; saveRequestObject.closedate = closingDate; saveRequestObject.closereasonid = closingReasonId; break; case StateEnum.callforrecords.name: saveRequestObject.paymentExpiryDate = "" - saveRequestObject.requeststatusid = StateEnum.callforrecords.id; + saveRequestObject.requeststatuslabel = StateEnum.callforrecords.label; if ( !("cfrDueDate" in saveRequestObject) || saveRequestObject.cfrDueDate === "" @@ -354,7 +354,7 @@ const BottomButtonGroup = React.memo( const status = Object.values(StateEnum).find( (statusValue) => statusValue.name === currentSelectedStatus ); - saveRequestObject.requeststatusid = status.id; + saveRequestObject.requeststatuslabel = status.label; if (currentSelectedStatus === StateEnum.onhold.name && !saveRequestObject.paymentExpiryDate) { saveRequestObject.paymentExpiryDate = dueDateCalculation(new Date(), PAYMENT_EXPIRY_DAYS); } diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index d754731d2..1da3db7ab 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -301,8 +301,8 @@ const FOIRequest = React.memo(({ userDetail }) => { const assignedTo = getAssignedTo(requestDetails); setAssignedToValue(assignedTo); if (Object.entries(requestDetails)?.length !== 0) { - let requestStateFromId = findRequestState(requestDetails.requeststatusid) - ? findRequestState(requestDetails.requeststatusid) + let requestStateFromId = findRequestState(requestDetails.requeststatuslabel) + ? findRequestState(requestDetails.requeststatuslabel) : StateEnum.unopened.name; setRequestState(requestStateFromId); settabStatus(requestStateFromId); diff --git a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/BottomButtonGroup.js b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/BottomButtonGroup.js index 1d2ef577e..14fd9def1 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/BottomButtonGroup.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/BottomButtonGroup.js @@ -186,34 +186,34 @@ const BottomButtonGroup = React.memo( const [successCount, setSuccessCount] = useState(0); const [fileCount, setFileCount] = useState(0); const [documents, setDocuments] = useState([]); - + const saveStatusId = () => { if (currentSelectedStatus) { switch (currentSelectedStatus.toLowerCase()) { case StateEnum.review.name.toLowerCase(): - saveMinistryRequestObject.requeststatusid = StateEnum.review.id; + saveMinistryRequestObject.requeststatuslabel = StateEnum.review.label; break; case StateEnum.feeassessed.name.toLowerCase(): - saveMinistryRequestObject.requeststatusid = - StateEnum.feeassessed.id; + saveMinistryRequestObject.requeststatuslabel = + StateEnum.feeassessed.label; break; case StateEnum.deduplication.name.toLowerCase(): - saveMinistryRequestObject.requeststatusid = - StateEnum.deduplication.id; + saveMinistryRequestObject.requeststatuslabel = + StateEnum.deduplication.label; break; case StateEnum.harms.name.toLowerCase(): - saveMinistryRequestObject.requeststatusid = StateEnum.harms.id; + saveMinistryRequestObject.requeststatuslabel = StateEnum.harms.label; break; case StateEnum.signoff.name.toLowerCase(): - saveMinistryRequestObject.requeststatusid = StateEnum.signoff.id; + saveMinistryRequestObject.requeststatuslabel = StateEnum.signoff.label; break; case StateEnum.response.name.toLowerCase(): saveMinistryRequestObject.ministrysignoffapproval = ministryApprovalState; - saveMinistryRequestObject.requeststatusid = StateEnum.response.id; + saveMinistryRequestObject.requeststatuslabel = StateEnum.response.label; break; case StateEnum.callforrecords.name.toLowerCase(): - saveMinistryRequestObject.requeststatusid = - StateEnum.callforrecords.id; + saveMinistryRequestObject.requeststatuslabel = + StateEnum.callforrecords.label; break; } } diff --git a/forms-flow-web/src/components/FOI/FOIRequest/RequestDetails.js b/forms-flow-web/src/components/FOI/FOIRequest/RequestDetails.js index 03f3005ef..43e4b4ae1 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/RequestDetails.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/RequestDetails.js @@ -126,7 +126,7 @@ const RequestDetails = React.memo( receivedDate: !!receivedDate ? formatDate(receivedDate): "", requestStartDate: startDate ? formatDate(startDate): "", dueDate: validateFields(requestDetails, FOI_COMPONENT_CONSTANTS.DUE_DATE, startDate ? formatDate(startDate): ""), - requestState: findRequestState(requestDetails?.requeststatusid) + requestState: findRequestState(requestDetails?.requeststatuslabel) } //event bubble up - sets the initial value to validate the required fields handleRequestDetailsInitialValue(requestDetailsObject); diff --git a/forms-flow-web/src/components/FOI/FOIRequest/utils.js b/forms-flow-web/src/components/FOI/FOIRequest/utils.js index f4aa33500..1ed724913 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/utils.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/utils.js @@ -359,10 +359,10 @@ export const alertUser = (e) => { e.returnValue = ""; }; -export const findRequestState = (requestStatusId) => { - if (requestStatusId != undefined) { +export const findRequestState = (requestStatusLabel) => { + if (requestStatusLabel != undefined) { let stateArray = Object.entries(StateEnum).find( - (value) => value[1].id === requestStatusId + (value) => value[1].label === requestStatusLabel ); return stateArray[1].name; } diff --git a/forms-flow-web/src/components/FOI/customComponents/ConfirmationModal/index.js b/forms-flow-web/src/components/FOI/customComponents/ConfirmationModal/index.js index a0ffb50ff..e727e9b4d 100644 --- a/forms-flow-web/src/components/FOI/customComponents/ConfirmationModal/index.js +++ b/forms-flow-web/src/components/FOI/customComponents/ConfirmationModal/index.js @@ -133,8 +133,8 @@ export default function ConfirmationModal({requestId, openModal, handleModal, st ( state.toLowerCase() === StateEnum.onhold.name.toLowerCase() && ( - saveRequestObject.requeststatusid === StateEnum.feeassessed.id - || saveRequestObject.requeststatusid === StateEnum.response.id + saveRequestObject.requeststatuslabel === StateEnum.feeassessed.label + || saveRequestObject.requeststatuslabel === StateEnum.response.label ) && saveRequestObject.email) ) @@ -150,22 +150,22 @@ export default function ConfirmationModal({requestId, openModal, handleModal, st let fileStatusTransition = ""; if (state.toLowerCase() === StateEnum.response.name.toLowerCase()) fileStatusTransition = StateTransitionCategories.signoffresponse.name; - else if (saveRequestObject.requeststatusid === StateEnum.callforrecords.id + else if (saveRequestObject.requeststatuslabel === StateEnum.callforrecords.label && state.toLowerCase() === StateEnum.review.name.toLowerCase()) fileStatusTransition = StateTransitionCategories.cfrreview.name; - else if (saveRequestObject.requeststatusid === StateEnum.harms.id + else if (saveRequestObject.requeststatuslabel === StateEnum.harms.label && state.toLowerCase() === StateEnum.review.name.toLowerCase()) fileStatusTransition = StateTransitionCategories.harmsreview.name; - else if (saveRequestObject.requeststatusid === StateEnum.feeassessed.id + else if (saveRequestObject.requeststatuslabel === StateEnum.feeassessed.label && state.toLowerCase() === StateEnum.onhold.name.toLowerCase()) fileStatusTransition = StateTransitionCategories.feeonhold.name; - else if (saveRequestObject.requeststatusid === StateEnum.response.id + else if (saveRequestObject.requeststatuslabel === StateEnum.response.label && state.toLowerCase() === StateEnum.onhold.name.toLowerCase()) fileStatusTransition = StateTransitionCategories.responseonhold.name; - else if (saveRequestObject.requeststatusid === StateEnum.response.id + else if (saveRequestObject.requeststatuslabel === StateEnum.response.label && state.toLowerCase() === StateEnum.review.name.toLowerCase()) fileStatusTransition = StateTransitionCategories.responsereview.name; - else if (saveRequestObject.requeststatusid === StateEnum.signoff.id + else if (saveRequestObject.requeststatuslabel === StateEnum.signoff.label && state.toLowerCase() === StateEnum.review.name.toLowerCase()) fileStatusTransition = StateTransitionCategories.signoffreview.name; @@ -206,7 +206,7 @@ export default function ConfirmationModal({requestId, openModal, handleModal, st (state.toLowerCase() === StateEnum.review.name.toLowerCase() && (!isAnyAmountPaid || !isMinistry)) || (state.toLowerCase() === StateEnum.onhold.name.toLowerCase() - && (saveRequestObject.requeststatusid === StateEnum.feeassessed.id || saveRequestObject.requeststatusid === StateEnum.response.id) + && (saveRequestObject.requeststatuslabel === StateEnum.feeassessed.label || saveRequestObject.requeststatuslabel === StateEnum.response.label) && saveRequestObject.email && cfrStatus == 'approved' && amountDue !== 0) @@ -226,7 +226,7 @@ export default function ConfirmationModal({requestId, openModal, handleModal, st
); } - else if (currentState?.toLowerCase() === StateEnum.signoff.name.toLowerCase() && state.toLowerCase() === StateEnum.response.name.toLowerCase() && saveRequestObject.requeststatusid === StateEnum.signoff.id) { + else if (currentState?.toLowerCase() === StateEnum.signoff.name.toLowerCase() && state.toLowerCase() === StateEnum.response.name.toLowerCase() && saveRequestObject.requeststatuslabel === StateEnum.signoff.label) { return (
@@ -312,7 +312,7 @@ export default function ConfirmationModal({requestId, openModal, handleModal, st
@@ -331,7 +331,7 @@ export default function ConfirmationModal({requestId, openModal, handleModal, st
diff --git a/forms-flow-web/src/components/FOI/customComponents/ConfirmationModal/util.js b/forms-flow-web/src/components/FOI/customComponents/ConfirmationModal/util.js index c24c79a58..5cd9c4e31 100644 --- a/forms-flow-web/src/components/FOI/customComponents/ConfirmationModal/util.js +++ b/forms-flow-web/src/components/FOI/customComponents/ConfirmationModal/util.js @@ -67,9 +67,9 @@ import { getFullnameList } from "../../../../helper/FOI/helper"; case StateEnum.review.name.toLowerCase(): if(!allowStateChange) return {title: "Changing the state", body: `Unable to change state until fee estimate actuals have been completed.`}; - else if (!isAnyAmountPaid && _saveRequestObject.requeststatusid === StateEnum.callforrecords.id) + else if (!isAnyAmountPaid && _saveRequestObject.requeststatuslabel === StateEnum.callforrecords.label) return {title: "Review Request", body: `Upload completed Call for Records form (if required) to change the state.`}; - else if (_saveRequestObject.requeststatusid === StateEnum.harms.id) + else if (_saveRequestObject.requeststatuslabel === StateEnum.harms.label) return {title: "Review Request", body: `Upload completed Call for Records form (if required) to change the state.`}; else return {title: "Changing the state", body: `Are you sure you want to change Request #${_requestNumber} to ${StateEnum.review.name}?`}; @@ -122,7 +122,7 @@ import { getFullnameList } from "../../../../helper/FOI/helper"; body: <>Are you sure you want to change Request #{_requestNumber} to on hold?
This will stop the clock and automatically email the applicant the fee estimate. }; } case StateEnum.response.name.toLowerCase(): - if (_saveRequestObject.requeststatusid === StateEnum.signoff.id) + if (_saveRequestObject.requeststatuslabel === StateEnum.signoff.label) return {title: "Ministry Sign Off", body: `Upload eApproval Logs, and enter in required approval fields to verify Ministry Approval and then change the state.`}; else return {title: "Changing the state", body: `Are you sure you want to change Request #${_requestNumber} to ${StateEnum.response.name}?`}; diff --git a/forms-flow-web/src/constants/FOI/statusEnum.js b/forms-flow-web/src/constants/FOI/statusEnum.js index b40603da1..6f226fa09 100644 --- a/forms-flow-web/src/constants/FOI/statusEnum.js +++ b/forms-flow-web/src/constants/FOI/statusEnum.js @@ -188,39 +188,27 @@ const MinistryStateList = Object.freeze({ // This corresponds to rows in the FOIRequestStatuses table on the backend const StateEnum = Object.freeze({ - open: { name: "Open", id: 1, label: "open" }, - callforrecords: { name: "Call For Records", id: 2, label: "callforrecords" }, - callforrecordsoverdue: { - name: "Call For Records Overdue", - id: -100, - label: "callforrecordsoverdue", - }, - closed: { name: "Closed", id: 3, label: "closed" }, - redirect: { name: "Redirect", id: 4, label: "redirect" }, - unopened: { name: "Unopened", id: 5, label: "unopened" }, - intakeinprogress: { - name: "Intake in Progress", - id: 6, - label: "intakeinprogress", - }, - review: { name: "Records Review", id: 7, label: "recordsreview" }, - feeassessed: { name: "Fee Estimate", id: 8, label: "feeestimate" }, - consult: { name: "Consult", id: 9, label: "consult" }, - signoff: { name: "Ministry Sign Off", id: 10, label: "ministrysignoff" }, - onhold: { name: "On Hold", id: 11, label: "onhold" }, - deduplication: { name: "Deduplication", id: 12, label: "deduplication" }, - harms: { name: "Harms Assessment", id: 13, label: "harmsassessment" }, - response: { name: "Response", id: 14, label: "response" }, - archived: { name: "Archived", id: 15, label: "archived" }, - peerreview: { name: "Peer Review", id: 16, label: "peerreview" }, - tagging: { name: "Tagging", id: 17, label: "tagging" }, - readytoscan: { name: "Ready to Scan", id: 18, label: "readytoscan" }, - appfeeowing: { name: "App Fee Owing", id: 19, label: "appfeeowing" }, - section5pending: { - name: "Section 5 Pending", - id: 20, - label: "section5pending", - }, + open: { name: "Open", label: "open" }, + callforrecords: { name: "Call For Records", label: "callforrecords" }, + callforrecordsoverdue: { name: "Call For Records Overdue", label: "callforrecordsoverdue" }, + closed: { name: "Closed", label: "closed" }, + redirect: { name: "Redirect", label: "redirect" }, + unopened: { name: "Unopened", label: "unopened" }, + intakeinprogress: { name: "Intake in Progress", label: "intakeinprogress" }, + review: { name: "Records Review", label: "recordsreview" }, + feeassessed: { name: "Fee Estimate", label: "feeestimate" }, + consult: { name: "Consult", label: "consult" }, + signoff: { name: "Ministry Sign Off", label: "ministrysignoff" }, + onhold: { name: "On Hold", label: "onhold" }, + deduplication: { name: "Deduplication", label: "deduplication" }, + harms: { name: "Harms Assessment", label: "harmsassessment" }, + response: { name: "Response", label: "response" }, + archived: { name: "Archived", label: "archived" }, + peerreview: { name: "Peer Review", label: "peerreview" }, + tagging: { name: "Tagging", label: "tagging" }, + readytoscan: { name: "Ready to Scan", label: "readytoscan" }, + appfeeowing: { name: "App Fee Owing", label: "appfeeowing" }, + section5pending: { name: "Section 5 Pending", label: "section5pending" }, }); const StateTransitionCategories = Object.freeze({ diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index cd6e2a8e9..3a7fed2f9 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 request_api.utils.enums import StateName class FOIMinistryRequest(db.Model): # Name of the table in our database @@ -68,7 +69,7 @@ class FOIMinistryRequest(db.Model): linkedrequests = db.Column(JSON, unique=False, nullable=True) identityverified = db.Column(JSON, unique=False, nullable=True) ministrysignoffapproval = db.Column(JSON, unique=False, nullable=True) - + requeststatuslabel = db.Column(db.String(50), nullable=False) #ForeignKey References @@ -106,13 +107,13 @@ def getrequest(cls,ministryrequestid): return request_schema.dump(query) @classmethod - def getLastStatusUpdateDate(cls,foiministryrequestid,requeststatusid): + def getLastStatusUpdateDate(cls,foiministryrequestid,requeststatuslabel): statusdate = None try: sql = """select created_at from "FOIMinistryRequests" - where foiministryrequestid = :foiministryrequestid and requeststatusid = :requeststatusid + where foiministryrequestid = :foiministryrequestid and requeststatuslabel = :requeststatuslabel order by version desc limit 1;""" - rs = db.session.execute(text(sql), {'foiministryrequestid': foiministryrequestid, 'requeststatusid': requeststatusid}) + rs = db.session.execute(text(sql), {'foiministryrequestid': foiministryrequestid, 'requeststatuslabel': requeststatuslabel}) statusdate = [row[0] for row in rs][0] except Exception as ex: logging.error(ex) @@ -163,11 +164,11 @@ def getrequests(cls, group = None): if group is None: _ministryrequestids = _session.query(distinct(FOIMinistryRequest.foiministryrequestid)).filter(FOIMinistryRequest.isactive == True).all() elif (group == IAOTeamWithKeycloackGroup.flex.value): - _ministryrequestids = _session.query(distinct(FOIMinistryRequest.foiministryrequestid)).filter(and_(FOIMinistryRequest.isactive == True), and_(and_(FOIMinistryRequest.assignedgroup == group),and_(FOIMinistryRequest.requeststatusid.in_([1,2,3,12,13,7,8,9,10,11,14,16,17,18])))).all() + _ministryrequestids = _session.query(distinct(FOIMinistryRequest.foiministryrequestid)).filter(and_(FOIMinistryRequest.isactive == True), and_(and_(FOIMinistryRequest.assignedgroup == group),and_(FOIMinistryRequest.requeststatuslabel.in_([StateName.open.name,StateName.callforrecords.name,StateName.closed.name,StateName.recordsreview.name,StateName.feeestimate.name,StateName.consult.name,StateName.ministrysignoff.value,StateName.onhold.name,StateName.deduplication.name,StateName.harmsassessment.name,StateName.response.name,StateName.peerreview.name,StateName.tagging.name,StateName.readytoscan.name])))).all() elif (group in ProcessingTeamWithKeycloackGroup.list()): - _ministryrequestids = _session.query(distinct(FOIMinistryRequest.foiministryrequestid)).filter(and_(FOIMinistryRequest.isactive == True), and_(and_(FOIMinistryRequest.assignedgroup == group),and_(FOIMinistryRequest.requeststatusid.in_([1,2,3,7,8,9,10,11,14,16,17,18])))).all() + _ministryrequestids = _session.query(distinct(FOIMinistryRequest.foiministryrequestid)).filter(and_(FOIMinistryRequest.isactive == True), and_(and_(FOIMinistryRequest.assignedgroup == group),and_(FOIMinistryRequest.requeststatuslabel.in_([StateName.open.name,StateName.callforrecords.name,StateName.closed.name,StateName.recordsreview.name,StateName.feeestimate.name,StateName.consult.name,StateName.ministrysignoff.value,StateName.onhold.name,StateName.response.name,StateName.peerreview.name,StateName.tagging.name,StateName.readytoscan.name])))).all() else: - _ministryrequestids = _session.query(distinct(FOIMinistryRequest.foiministryrequestid)).filter(and_(FOIMinistryRequest.isactive == True), or_(and_(FOIMinistryRequest.assignedgroup == group),and_(FOIMinistryRequest.assignedministrygroup == group,or_(FOIMinistryRequest.requeststatusid.in_([2,7,9,8,10,11,12,13,14,16,17,18]))))).all() + _ministryrequestids = _session.query(distinct(FOIMinistryRequest.foiministryrequestid)).filter(and_(FOIMinistryRequest.isactive == True), or_(and_(FOIMinistryRequest.assignedgroup == group),and_(FOIMinistryRequest.assignedministrygroup == group,or_(FOIMinistryRequest.requeststatuslabel.in_([StateName.callforrecords.name,StateName.recordsreview.name,StateName.feeestimate.name,StateName.consult.name,StateName.ministrysignoff.name,StateName.onhold.name,StateName.deduplication.name,StateName.harmsassessment.name,StateName.response.name,StateName.peerreview.name,StateName.tagging.name,StateName.readytoscan.name]))))).all() _requests = [] ministryrequest_schema = FOIMinistryRequestSchema() @@ -226,10 +227,11 @@ def getrequestById(cls,ministryrequestid): def getrequeststatusById(cls,ministryrequestid): summary = [] try: - sql = 'select foirequest_id, version, requeststatusid, created_at from "FOIMinistryRequests" fr where foiministryrequestid = :ministryrequestid and requeststatusid != 3 order by version desc;' - rs = db.session.execute(text(sql), {'ministryrequestid': ministryrequestid}) + sql = 'select foirequest_id, version, requeststatusid, requeststatuslabel, created_at from "FOIMinistryRequests" fr where foiministryrequestid = :ministryrequestid and requeststatuslabel != :requeststatuslabel order by version desc;' + + rs = db.session.execute(text(sql), {'ministryrequestid': ministryrequestid, 'requeststatuslabel': StateName.closed.name}) for row in rs: - summary.append({"requeststatusid": row["requeststatusid"], "created_at": row["created_at"], "foirequest_id": row["foirequest_id"]}) + summary.append({"requeststatusid": row["requeststatusid"], "requeststatuslabel": row["requeststatuslabel"], "created_at": row["created_at"], "foirequest_id": row["foirequest_id"]}) except Exception as ex: logging.error(ex) raise ex @@ -406,13 +408,13 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us else_ = FOIMinistryRequest.assignedministrygroup).label('ministryAssignedToFormatted') duedate = case([ - (FOIMinistryRequest.requeststatusid == 11, # On Hold + (FOIMinistryRequest.requeststatuslabel == StateName.onhold.name, # On Hold literal(None)), ], else_ = cast(FOIMinistryRequest.duedate, String)).label('duedate') cfrduedate = case([ - (FOIMinistryRequest.requeststatusid == 11, # On Hold + (FOIMinistryRequest.requeststatuslabel == StateName.onhold.name, # On Hold literal(None)), ], else_ = cast(FOIMinistryRequest.cfrduedate, String)).label('cfrduedate') @@ -553,7 +555,7 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us SubjectCode, SubjectCode.subjectcodeid == FOIMinistryRequestSubjectCode.subjectcodeid, isouter=True - ).filter(FOIMinistryRequest.requeststatusid != 3) + ).filter(FOIMinistryRequest.requeststatuslabel != StateName.closed.name) if(additionalfilter == 'watchingRequests'): #watchby @@ -682,7 +684,7 @@ def getgroupfilters(cls, groups): FOIMinistryRequest.assignedgroup == group, and_( FOIMinistryRequest.assignedgroup == IAOTeamWithKeycloackGroup.flex.value, - FOIMinistryRequest.requeststatusid.in_([1]) + FOIMinistryRequest.requeststatuslabel.in_([StateName.open.name]) ) ) ) @@ -692,7 +694,7 @@ def getgroupfilters(cls, groups): FOIMinistryRequest.assignedgroup == group, and_( FOIMinistryRequest.assignedministrygroup == group, - FOIMinistryRequest.requeststatusid.in_([2,7,9,8,10,11,12,13,14,16,17,18]) + FOIMinistryRequest.requeststatuslabel.in_([StateName.callforrecords.name,StateName.recordsreview.name,StateName.feeestimate.name,StateName.consult.name,StateName.ministrysignoff.name,StateName.onhold.name,StateName.deduplication.name,StateName.harmsassessment.name,StateName.response.name,StateName.peerreview.name,StateName.tagging.name,StateName.readytoscan.name]) ) ) ) @@ -707,7 +709,7 @@ def getgroupfilters(cls, groups): @classmethod def getrequestoriginalduedate(cls,ministryrequestid): - return db.session.query(FOIMinistryRequest.duedate).filter(FOIMinistryRequest.foiministryrequestid == ministryrequestid, FOIMinistryRequest.requeststatusid == 1).order_by(FOIMinistryRequest.version).first()[0] + return db.session.query(FOIMinistryRequest.duedate).filter(FOIMinistryRequest.foiministryrequestid == ministryrequestid, FOIMinistryRequest.requeststatuslabel == StateName.open.name).order_by(FOIMinistryRequest.version).first()[0] @classmethod def getduedate(cls,ministryrequestid): @@ -719,10 +721,10 @@ def getupcomingcfrduerecords(cls): upcomingduerecords = [] try: sql = """select distinct on (filenumber) filenumber, to_char(cfrduedate, 'YYYY-MM-DD') as cfrduedate, foiministryrequestid, version, foirequest_id, created_at, createdby from "FOIMinistryRequests" fpa - where isactive = true and cfrduedate is not null and requeststatusid = 2 + where isactive = true and cfrduedate is not null and requeststatuslabel = :requeststatuslabel and cfrduedate between NOW() - INTERVAL '7 DAY' AND NOW() + INTERVAL '7 DAY' order by filenumber , version desc;""" - rs = db.session.execute(text(sql)) + rs = db.session.execute(text(sql), {'requeststatuslabel': StateName.callforrecords.name}) for row in rs: upcomingduerecords.append({"filenumber": row["filenumber"], "cfrduedate": row["cfrduedate"],"foiministryrequestid": row["foiministryrequestid"], "version": row["version"], "foirequest_id": row["foirequest_id"], "created_at": row["created_at"], "createdby": row["createdby"]}) except Exception as ex: @@ -737,10 +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 requeststatusid not in (5,6,4,11,3,15) + 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;""" - rs = db.session.execute(text(sql)) + rs = db.session.execute(text(sql), {'requeststatuslabel': [StateName.closed.name,StateName.redirect.name,StateName.unopened.name,StateName.intakeinprogress.name,StateName.onhold.name,StateName.archived.name]}) 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"]}) except Exception as ex: @@ -758,14 +760,15 @@ def getupcomingdivisionduerecords(cls): frd.divisionid, frd.stageid, pad2."name" divisionname, pads."name" stagename, to_char(divisionduedate, 'YYYY-MM-DD') as duedate, frd.created_at, frd.createdby from "FOIMinistryRequestDivisions" frd - inner join (select distinct on (fpa.foiministryrequestid) foiministryrequestid, version as foiministryrequestversion, axisrequestid, filenumber, foirequest_id, requeststatusid + 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.requeststatusid not in (5,6,4,11,3,15) + 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;""" - rs = db.session.execute(text(sql)) + rs = db.session.execute(text(sql), {'requeststatuslabel': [StateName.closed.name,StateName.redirect.name,StateName.unopened.name,StateName.intakeinprogress.name,StateName.onhold.name,StateName.archived.name]}) + for row in rs: upcomingduerecords.append({"axisrequestid": row["axisrequestid"], "filenumber": row["filenumber"], "foiministryrequestid": row["foiministryrequestid"], "version": row["foiministryrequestversion"], @@ -849,9 +852,9 @@ def getclosedaxisids(cls): try: sql = """ select distinct on (foiministryrequestid) foiministryrequestid, version, axisrequestid from "FOIMinistryRequests" fr - where requeststatusid = 3 + where requeststatuslabel = :requeststatuslabel order by foiministryrequestid , version desc, axisrequestid""" - rs = db.session.execute(text(sql)) + rs = db.session.execute(text(sql), {'requeststatuslabel': StateName.closed.name}) for row in rs: axisids.append(row["axisrequestid"]) except Exception as ex: @@ -926,13 +929,13 @@ def getbasequery(cls, iaoassignee, ministryassignee, userid=None, requestby='IAO else_ = FOIMinistryRequest.assignedministrygroup).label('ministryAssignedToFormatted') duedate = case([ - (FOIMinistryRequest.requeststatusid == 11, # On Hold + (FOIMinistryRequest.requeststatuslabel == StateName.onhold.name, # On Hold literal(None)), ], else_ = cast(FOIMinistryRequest.duedate, String)).label('duedate') cfrduedate = case([ - (FOIMinistryRequest.requeststatusid == 11, # On Hold + (FOIMinistryRequest.requeststatuslabel == StateName.onhold.name, # On Hold literal(None)), ], else_ = cast(FOIMinistryRequest.cfrduedate, String)).label('cfrduedate') @@ -1116,7 +1119,7 @@ def advancedsearch(cls, params, userid, isministryrestrictedfilemanager = False) groupfilter.append(FOIMinistryRequest.assignedministrygroup == group) #ministry advanced search show cfr onwards - statefilter = FOIMinistryRequest.requeststatusid.in_([2,3,7,9,8,10,11,12,13,14,16,17,18]) + statefilter = FOIMinistryRequest.requeststatuslabel.in_([StateName.callforrecords.name,StateName.closed.name,StateName.recordsreview.name,StateName.feeestimate.name,StateName.consult.name,StateName.ministrysignoff.name,StateName.onhold.name,StateName.deduplication.name,StateName.harmsassessment.name,StateName.response.name,StateName.peerreview.name,StateName.tagging.name,StateName.readytoscan.name]) ministry_queue = FOIMinistryRequest.advancedsearchsubquery(params, iaoassignee, ministryassignee, userid, 'Ministry', False, isministryrestrictedfilemanager).filter(and_(or_(*groupfilter), statefilter)) @@ -1153,10 +1156,10 @@ def getfilterforadvancedsearch(cls, params, iaoassignee, ministryassignee): # return all except closed if(includeclosed == False): - filtercondition.append(FOIMinistryRequest.requeststatusid != 3) + filtercondition.append(FOIMinistryRequest.requeststatuslabel != StateName.closed.name) elif(len(params['requeststatus']) > 1 and includeclosed == False): # return all except closed - filtercondition.append(FOIMinistryRequest.requeststatusid != 3) + filtercondition.append(FOIMinistryRequest.requeststatuslabel != StateName.closed.name) #request type: personal, general if(len(params['requesttype']) > 0): @@ -1185,9 +1188,9 @@ def getfilterforadvancedsearch(cls, params, iaoassignee, ministryassignee): def getfilterforrequeststate(cls, params, includeclosed): #request state: unopened, call for records, etc. requeststatecondition = [] - for stateid in params['requeststate']: - requeststatecondition.append(FOIMinistryRequest.requeststatusid == stateid) - if(stateid == 3): + for statelabel in params['requeststate']: + requeststatecondition.append(FOIMinistryRequest.requeststatuslabel == statelabel) + if(statelabel == StateName.closed.name): includeclosed = True return {'condition': or_(*requeststatecondition), 'includeclosed': includeclosed} @@ -1196,8 +1199,8 @@ def getfilterforrequeststatus(cls, params, iaoassignee, ministryassignee): #request status: overdue || on time if(params['requeststatus'][0] == 'overdue'): #exclude "on hold" for overdue - stateid = 11 - return and_(FOIMinistryRequest.findfield('duedate', iaoassignee, ministryassignee) < datetime.now().date(), FOIMinistryRequest.requeststatusid != stateid) + statelabel = StateName.onhold.name + return and_(FOIMinistryRequest.findfield('duedate', iaoassignee, ministryassignee) < datetime.now().date(), FOIMinistryRequest.requeststatuslabel != statelabel) else: return FOIMinistryRequest.findfield('duedate', iaoassignee, ministryassignee) >= datetime.now().date() @@ -1302,9 +1305,9 @@ def getofflinepaymentflag(cls,ministryrequestid): class FOIMinistryRequestSchema(ma.Schema): class Meta: fields = ('foiministryrequestid','version','filenumber','description','recordsearchfromdate','recordsearchtodate', - 'startdate','duedate','assignedgroup','assignedto','programarea.programareaid','requeststatus.requeststatusid', + 'startdate','duedate','assignedgroup','assignedto','programarea.programareaid', 'foirequest.foirequestid','foirequest.requesttype','foirequest.receiveddate','foirequest.deliverymodeid', - 'foirequest.receivedmodeid','requeststatus.requeststatusid','requeststatus.name','programarea.bcgovcode', + 'foirequest.receivedmodeid','requeststatus.requeststatusid','requeststatuslabel','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') diff --git a/request-management-api/request_api/models/FOIRawRequests.py b/request-management-api/request_api/models/FOIRawRequests.py index 9a0169647..b7588d84c 100644 --- a/request-management-api/request_api/models/FOIRawRequests.py +++ b/request-management-api/request_api/models/FOIRawRequests.py @@ -18,6 +18,7 @@ import logging from dateutil import parser import json +from request_api.utils.enums import StateName class FOIRawRequest(db.Model): # Name of the table in our database @@ -27,6 +28,7 @@ class FOIRawRequest(db.Model): version = db.Column(db.Integer, primary_key=True,nullable=False) requestrawdata = db.Column(JSON, unique=False, nullable=True) status = db.Column(db.String(25), unique=False, nullable=True) + requeststatuslabel = db.Column(db.String(50), unique=False, nullable=False) notes = db.Column(db.String(120), unique=False, nullable=True) wfinstanceid = db.Column(UUID(as_uuid=True), unique=False, nullable=True) assignedgroup = db.Column(db.String(250), unique=False, nullable=True) @@ -55,7 +57,7 @@ class FOIRawRequest(db.Model): @classmethod def saverawrequest(cls, _requestrawdata, sourceofsubmission, ispiiredacted, userid, notes, requirespayment, axisrequestid, axissyncdate, linkedrequests, assigneegroup=None, assignee=None, assigneefirstname=None, assigneemiddlename=None, assigneelastname=None)->DefaultMethodResult: version = 1 - newrawrequest = FOIRawRequest(requestrawdata=_requestrawdata, status = 'Unopened' if sourceofsubmission != "intake" else 'Intake in Progress', createdby=userid, version=version, sourceofsubmission=sourceofsubmission, assignedgroup=assigneegroup, assignedto=assignee, ispiiredacted=ispiiredacted, notes=notes, requirespayment=requirespayment, axisrequestid=axisrequestid, axissyncdate=axissyncdate, linkedrequests=linkedrequests) + newrawrequest = FOIRawRequest(requestrawdata=_requestrawdata, status = StateName.unopened.value if sourceofsubmission != "intake" else StateName.intakeinprogress.value, requeststatuslabel = StateName.unopened.name if sourceofsubmission != "intake" else StateName.intakeinprogress.name, createdby=userid, version=version, sourceofsubmission=sourceofsubmission, assignedgroup=assigneegroup, assignedto=assignee, ispiiredacted=ispiiredacted, notes=notes, requirespayment=requirespayment, axisrequestid=axisrequestid, axissyncdate=axissyncdate, linkedrequests=linkedrequests) if assignee is not None: FOIAssignee.saveassignee(assignee, assigneefirstname, assigneemiddlename, assigneelastname) @@ -66,13 +68,13 @@ def saverawrequest(cls, _requestrawdata, sourceofsubmission, ispiiredacted, user @classmethod def saverawrequest_foipayment(cls,_requestrawdata,notes, requirespayment, ispiiredacted)->DefaultMethodResult: version = 1 - newrawrequest = FOIRawRequest(requestrawdata=_requestrawdata, status='Unopened',createdby=None,version=version,sourceofsubmission="onlineform",assignedgroup=None,assignedto=None,ispiiredacted=ispiiredacted,notes=notes, requirespayment= requirespayment) + newrawrequest = FOIRawRequest(requestrawdata=_requestrawdata, status=StateName.unopened.value, requeststatuslabel = StateName.unopened.name ,createdby=None,version=version,sourceofsubmission="onlineform",assignedgroup=None,assignedto=None,ispiiredacted=ispiiredacted,notes=notes, requirespayment= requirespayment) db.session.add(newrawrequest) db.session.commit() return DefaultMethodResult(True,'Request added',newrawrequest.requestid) @classmethod - def saverawrequestversion(cls,_requestrawdata,requestid,assigneegroup,assignee,status,ispiiredacted,userid,assigneefirstname=None,assigneemiddlename=None,assigneelastname=None)->DefaultMethodResult: + def saverawrequestversion(cls,_requestrawdata,requestid,assigneegroup,assignee,status,ispiiredacted,userid,statuslabel,assigneefirstname=None,assigneemiddlename=None,assigneelastname=None)->DefaultMethodResult: request = db.session.query(FOIRawRequest).filter_by(requestid=requestid).order_by(FOIRawRequest.version.desc()).first() if request is not None: _assginee = assignee if assignee not in (None,'') else None @@ -94,6 +96,7 @@ def saverawrequestversion(cls,_requestrawdata,requestid,assigneegroup,assignee,s updatedby=None, updated_at=datetime.now(), status=status, + requeststatuslabel=statuslabel, assignedgroup=assigneegroup, assignedto=_assginee, wfinstanceid=request.wfinstanceid, @@ -297,7 +300,7 @@ def getDescriptionSummaryById(cls, requestid): requests = [] try: sql = """select * , - CASE WHEN description = (select requestrawdata -> 'descriptionTimeframe' ->> 'description' from "FOIRawRequests" where requestid = :requestid and status = 'Unopened' and version = 1) + CASE WHEN description = (select requestrawdata -> 'descriptionTimeframe' ->> 'description' from "FOIRawRequests" where requestid = :requestid and status = :requeststatus and version = 1) then 'Online Form' else savedby END as createdby from (select CASE WHEN lower(status) <> 'unopened' @@ -312,7 +315,7 @@ def getDescriptionSummaryById(cls, requestid): to_char(created_at, 'YYYY-MM-DD HH24:MI:SS') as createdat, status, ispiiredacted, createdby as savedby from "FOIRawRequests" fr where requestid = :requestid order by version ) as sq;""" - rs = db.session.execute(text(sql), {'requestid': requestid}) + rs = db.session.execute(text(sql), {'requestid': requestid, 'requeststatus': StateName.unopened.value}) for row in rs: requests.append(dict(row)) except Exception as ex: @@ -368,10 +371,10 @@ def getappfeeowingrequests(cls): # with the reminder date sql = ''' SELECT * FROM (SELECT DISTINCT ON (requestid) requestid, updated_at, status FROM public."FOIRawRequests" ORDER BY requestid ASC, version DESC) r - WHERE r.status = 'App Fee Owing' + WHERE r.status = :requeststaus order by r.updated_at asc ''' - rs = db.session.execute(text(sql)) + rs = db.session.execute(text(sql), {'requeststaus': StateName.appfeeowing.value}) appfeeowingrequests = rs except Exception as ex: logging.error(ex) @@ -441,47 +444,47 @@ def getbasequery(cls, additionalfilter=None, userid=None, isiaorestrictedfileman ] requesttype = case([ - (FOIRawRequest.status == 'Unopened', + (FOIRawRequest.status == StateName.unopened.value, FOIRawRequest.requestrawdata['requestType']['requestType'].astext), ], else_ = FOIRawRequest.requestrawdata['requestType'].astext).label('requestType') firstname = case([ - (FOIRawRequest.status == 'Unopened', + (FOIRawRequest.status == StateName.unopened.value, FOIRawRequest.requestrawdata['contactInfo']['firstName'].astext), ], else_ = FOIRawRequest.requestrawdata['firstName'].astext).label('firstName') lastname = case([ - (FOIRawRequest.status == 'Unopened', + (FOIRawRequest.status == StateName.unopened.value, FOIRawRequest.requestrawdata['contactInfo']['lastName'].astext), ], else_ = FOIRawRequest.requestrawdata['lastName'].astext).label('lastName') description = case([ - (FOIRawRequest.status == 'Unopened', + (FOIRawRequest.status == StateName.unopened.value, FOIRawRequest.requestrawdata['descriptionTimeframe']['description'].astext), ], else_ = FOIRawRequest.requestrawdata['description'].astext).label('description') recordsearchfromdate = case([ - (FOIRawRequest.status == 'Unopened', + (FOIRawRequest.status == StateName.unopened.value, FOIRawRequest.requestrawdata['descriptionTimeframe']['fromDate'].astext), ], else_ = FOIRawRequest.requestrawdata['fromDate'].astext).label('recordsearchfromdate') recordsearchtodate = case([ - (FOIRawRequest.status == 'Unopened', + (FOIRawRequest.status == StateName.unopened.value, FOIRawRequest.requestrawdata['descriptionTimeframe']['toDate'].astext), ], else_ = FOIRawRequest.requestrawdata['toDate'].astext).label('recordsearchtodate') duedate = case([ - (FOIRawRequest.status == 'Unopened', + (FOIRawRequest.status == StateName.unopened.value, literal(None)), ], else_ = FOIRawRequest.requestrawdata['dueDate'].astext).label('duedate') receiveddate = case([ - (and_(FOIRawRequest.status == 'Unopened', FOIRawRequest.requestrawdata['receivedDate'].is_(None)), + (and_(FOIRawRequest.status == StateName.unopened.value, FOIRawRequest.requestrawdata['receivedDate'].is_(None)), func.to_char(FOIRawRequest.created_at, 'YYYY-mm-DD')), ], else_ = FOIRawRequest.requestrawdata['receivedDate'].astext).label('receivedDate') receiveddateuf = case([ - (and_(FOIRawRequest.status == 'Unopened', FOIRawRequest.requestrawdata['receivedDateUF'].is_(None)), + (and_(FOIRawRequest.status == StateName.unopened.value, FOIRawRequest.requestrawdata['receivedDateUF'].is_(None)), func.to_char(FOIRawRequest.created_at, 'YYYY-mm-DD HH:MM:SS')), ], else_ = FOIRawRequest.requestrawdata['receivedDateUF'].astext).label('receivedDateUF') @@ -612,7 +615,7 @@ def getbasequery(cls, additionalfilter=None, userid=None, isiaorestrictedfileman @classmethod def getrequestssubquery(cls, filterfields, keyword, additionalfilter, userid, isiaorestrictedfilemanager): basequery = FOIRawRequest.getbasequery(additionalfilter, userid, isiaorestrictedfilemanager) - basequery = basequery.filter(FOIRawRequest.status != 'Unopened').filter(FOIRawRequest.status != 'Closed') + basequery = basequery.filter(FOIRawRequest.status != StateName.unopened.value).filter(FOIRawRequest.status != StateName.closed.value) #filter/search if(len(filterfields) > 0 and keyword is not None): filtercondition = FOIRawRequest.getfilterforrequestssubquery(filterfields, keyword) @@ -775,7 +778,7 @@ def getfilterforadvancedsearch(cls, params): filtercondition.append(requeststatecondition['condition']) includeclosed = requeststatecondition['includeclosed'] else: - filtercondition.append(FOIRawRequest.status != 'Unopened') #not return Unopened by default + filtercondition.append(FOIRawRequest.status != StateName.unopened.value) #not return Unopened by default #request status: overdue, on time - no due date for unopen & intake in progress, so return all except closed if(len(params['requeststatus']) > 0 and includeclosed == False): @@ -783,7 +786,7 @@ def getfilterforadvancedsearch(cls, params): #no rawrequest returned for this case filtercondition.append(FOIRawRequest.status == 'ReturnNothing') else: - filtercondition.append(FOIRawRequest.status != 'Closed') + filtercondition.append(FOIRawRequest.status != StateName.closed.value) #request type: personal, general if(len(params['requesttype']) > 0): @@ -845,14 +848,14 @@ def getfilterforrequeststate(cls, params, includeclosed): requeststatecondition = [] for state in params['requeststate']: if(state == '3'): - requeststatecondition.append(FOIRawRequest.status == 'Closed') + requeststatecondition.append(FOIRawRequest.status == StateName.closed.value) includeclosed = True elif(state == '4'): - requeststatecondition.append(FOIRawRequest.status == 'Redirect') + requeststatecondition.append(FOIRawRequest.status == StateName.redirect.value) elif(state == '5'): - requeststatecondition.append(FOIRawRequest.status == 'Unopened') + requeststatecondition.append(FOIRawRequest.status == StateName.unopened.value) elif(state == '6'): - requeststatecondition.append(FOIRawRequest.status == 'Intake in Progress') + requeststatecondition.append(FOIRawRequest.status == StateName.intakeinprogress.value) if(len(requeststatecondition) == 0): requeststatecondition.append(FOIRawRequest.status == 'Not Applicable') #searched state does not apply to rawrequests @@ -1009,8 +1012,8 @@ def getlatestsection5pendings(cls): (SELECT DISTINCT ON (requestid) requestid, created_at, version, status, axisrequestid FROM public."FOIRawRequests" ORDER BY requestid ASC, version DESC) foireqs - WHERE foireqs.status = 'Section 5 Pending';""" - rs = db.session.execute(text(sql)) + WHERE foireqs.status = :requeststatus;""" + rs = db.session.execute(text(sql), {'requeststatus': StateName.section5pending.value}) for row in rs: section5pendings.append({"requestid": row["requestid"], "version": row["version"], "statusname": row["status"], "created_at": row["created_at"], "axisrequestid": ["axisrequestid"]}) except Exception as ex: @@ -1022,4 +1025,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', 'requeststatuslabel', '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 diff --git a/request-management-api/request_api/models/FOIRequestNotificationUsers.py b/request-management-api/request_api/models/FOIRequestNotificationUsers.py index 148d8be9f..ec5ef8f46 100644 --- a/request-management-api/request_api/models/FOIRequestNotificationUsers.py +++ b/request-management-api/request_api/models/FOIRequestNotificationUsers.py @@ -212,7 +212,7 @@ def geteventsubquery(cls, groups, filterfields, keyword, additionalfilter, useri ).join( FOINotifications, and_(FOINotifications.axisnumber == FOIRequests.axisrequestid), - ).filter(FOIRequests.requeststatusid != 3) + ).filter(FOIRequests.requeststatuslabel != StateName.closed.name) if(additionalfilter == 'watchingRequests'): #watchby @@ -262,7 +262,7 @@ def getgroupfilters(cls, groups): FOIRequests.assignedgroup == group, and_( FOIRequests.assignedgroup == IAOTeamWithKeycloackGroup.flex.value, - FOIRequests.requeststatusid.in_([1]) + FOIRequests.requeststatuslabel.in_([StateName.open.name]) ) ) ) @@ -272,7 +272,7 @@ def getgroupfilters(cls, groups): FOIRequests.assignedgroup == group, and_( FOIRequests.assignedministrygroup == group, - FOIRequests.requeststatusid.in_([2,7,9,8,10,11,12,13,14,17,18]) + FOIRequests.requeststatuslabel.in_([StateName.callforrecords.name,StateName.recordsreview.name,StateName.feeestimate.name,StateName.consult.name,StateName.ministrysignoff.name,StateName.onhold.name,StateName.deduplication.name,StateName.harmsassessment.name,StateName.response.name,StateName.tagging.name,StateName.readytoscan.name]) ) ) ) diff --git a/request-management-api/request_api/models/FOIRequestStatus.py b/request-management-api/request_api/models/FOIRequestStatus.py index fa751e971..439c9f6ed 100644 --- a/request-management-api/request_api/models/FOIRequestStatus.py +++ b/request-management-api/request_api/models/FOIRequestStatus.py @@ -9,6 +9,7 @@ class FOIRequestStatus(db.Model): name = db.Column(db.String(100), unique=False, nullable=False) description = db.Column(db.String(255), unique=False, nullable=True) isactive = db.Column(db.Boolean, unique=False, nullable=False) + statuslabel = db.Column(db.String(50), unique=True, nullable=False) @classmethod def getrequeststatuses(cls): @@ -17,17 +18,17 @@ def getrequeststatuses(cls): return requeststatus_schema.dump(query) @classmethod - def getrequeststatusid(cls,status): + def getrequeststatus(cls,status): requeststatus_schema = RequestStatusSchema() query = db.session.query(FOIRequestStatus).filter_by(name=status).first() return requeststatus_schema.dump(query) @classmethod - def getrequeststatusname(cls,statusid): + def getrequeststatusbylabel(cls,statuslabel): requeststatus_schema = RequestStatusSchema() - query = db.session.query(FOIRequestStatus).filter_by(requeststatusid=statusid, isactive=True).first() + query = db.session.query(FOIRequestStatus).filter_by(statuslabel=statuslabel, isactive=True).first() return requeststatus_schema.dump(query) class RequestStatusSchema(ma.Schema): class Meta: - fields = ('requeststatusid', 'name', 'description','isactive') \ No newline at end of file + fields = ('requeststatusid', 'name', 'description','isactive','statuslabel') \ No newline at end of file diff --git a/request-management-api/request_api/models/FOIRequestTeams.py b/request-management-api/request_api/models/FOIRequestTeams.py index 02d02714b..e6ddbe50f 100644 --- a/request-management-api/request_api/models/FOIRequestTeams.py +++ b/request-management-api/request_api/models/FOIRequestTeams.py @@ -4,12 +4,15 @@ from sqlalchemy.sql.schema import ForeignKey from sqlalchemy import text import logging +from request_api.utils.enums import StateName + class FOIRequestTeam(db.Model): __tablename__ = 'FOIRequestTeams' # Defining the columns requestteamid = db.Column(db.Integer, primary_key=True,autoincrement=True) requesttype = db.Column(db.String(100), unique=False, nullable=True) requeststatusid = db.Column(db.Integer,ForeignKey('FOIRequestStatuses.requeststatusid')) + requeststatuslabel = db.Column(db.String(50), unique=False, nullable=False) teamid = db.Column(db.Integer,ForeignKey('OperatingTeams.teamid')) programareaid = db.Column(db.Integer,ForeignKey('ProgramAreas.programareaid')) isactive = db.Column(db.Boolean, unique=False, nullable=False) @@ -23,14 +26,15 @@ def getrequestteams(cls): @classmethod def getteamsbystatusandprogramarea(cls, requesttype, status, bcgovcode): teams = [] - try: + try: + # and replace(lower(fs2."name"),' ','') = :status sql = """ with mappedteams as ( select ot."name" as name, ot."type" as type, ft.requestteamid as orderby from "FOIRequestTeams" ft inner join "FOIRequestStatuses" fs2 on ft.requeststatusid = fs2.requeststatusid inner join "OperatingTeams" ot on ft.teamid = ot.teamid left join "ProgramAreas" pa on ft.programareaid = pa.programareaid - where ft.isactive = true and lower(ft.requesttype) = :requesttype - and replace(lower(fs2."name"),' ','') = :status + where ft.isactive = true and lower(ft.requesttype) = :requesttype + and ft.requeststatuslabel = :status and (lower(pa.bcgovcode) = :bcgovcode or ft.programareaid is null) ) -- remove the with statement and below query go back to mapped teams only in assignee drop down @@ -57,8 +61,8 @@ def getprocessingteamsbytype(cls, requesttype): inner join "ProgramAreas" pa on ft.programareaid = pa.programareaid where lower(ft.requesttype) = :requesttype and ft.programareaid is not null and ot."type" = 'iao' - and ft.requeststatusid = 8""" - rs = db.session.execute(text(sql), {'requesttype': requesttype}) + and ft.requeststatuslabel = :requeststatuslabel""" + rs = db.session.execute(text(sql), {'requesttype': requesttype, 'requeststatuslabel': StateName.feeestimate.name}) for row in rs: teams.append({"team":row["team"], "ministry":row["ministry"], "bcgovcode":row["bcgovcode"], "iaocode":row["iaocode"]}) except Exception as ex: @@ -91,4 +95,4 @@ def getdefaultprocessingteamforpersonal(cls, bcgovcode): class FOIRequestTeamSchema(ma.Schema): class Meta: - fields = ('requestteamid', 'requesttype', 'requeststatusid','teamid','programareaid','isactive') \ No newline at end of file + fields = ('requestteamid', 'requesttype', 'requeststatusid','teamid','programareaid','isactive', 'requeststatuslabel') \ No newline at end of file diff --git a/request-management-api/request_api/models/views/FOIRequests.py b/request-management-api/request_api/models/views/FOIRequests.py index b4a85ddc8..baa3395f3 100644 --- a/request-management-api/request_api/models/views/FOIRequests.py +++ b/request-management-api/request_api/models/views/FOIRequests.py @@ -20,4 +20,5 @@ class FOIRequests(db.Model): ministryassignedtoformatted = db.Column(db.String(500)) description = db.Column(db.Text) crtid = db.Column(db.Text) + requeststatuslabel = db.Column(db.String(50)) diff --git a/request-management-api/request_api/resources/foirequest.py b/request-management-api/request_api/resources/foirequest.py index 290cd2ccc..58cf30376 100644 --- a/request-management-api/request_api/resources/foirequest.py +++ b/request-management-api/request_api/resources/foirequest.py @@ -28,6 +28,7 @@ from request_api.services.eventservice import eventservice from request_api.schemas.foirequestwrapper import FOIRequestWrapperSchema, EditableFOIRequestWrapperSchema, FOIRequestMinistrySchema, FOIRequestStatusSchema from request_api.schemas.foiassignee import FOIRequestAssigneeSchema +from request_api.utils.enums import StateName from marshmallow import Schema, fields, validate, ValidationError from request_api.utils.enums import MinistryTeamWithKeycloackGroup import json @@ -99,7 +100,7 @@ def post(): assignedtofirstname = request_json["assignedToFirstName"] if request_json.get("assignedToFirstName") != None else None assignedtomiddlename = request_json["assignedToMiddleName"] if request_json.get("assignedToMiddleName") != None else None assignedtolastname = request_json["assignedToLastName"] if request_json.get("assignedToLastName") != None else None - rawresult = rawrequestservice().saverawrequestversion(request_json,request_json['id'],assignedgroup,assignedto,"Archived",AuthHelper.getuserid(), assignedtofirstname,assignedtomiddlename,assignedtolastname) + rawresult = rawrequestservice().saverawrequestversion(request_json,request_json['id'],assignedgroup,assignedto,"Archived",AuthHelper.getuserid(), assignedtofirstname,assignedtomiddlename,assignedtolastname,StateName.archived.name) diff --git a/request-management-api/request_api/resources/request.py b/request-management-api/request_api/resources/request.py index cfc9fc012..58768694a 100644 --- a/request-management-api/request_api/resources/request.py +++ b/request-management-api/request_api/resources/request.py @@ -25,6 +25,7 @@ from request_api.services.rawrequestservice import rawrequestservice from request_api.services.documentservice import documentservice from request_api.services.eventservice import eventservice +from request_api.utils.enums import StateName import json import asyncio from jose import jwt as josejwt @@ -92,12 +93,13 @@ def post(requestid=None, actiontype=None): assigneefirstname = requestdata['assigneefirstname'] assigneemiddlename = requestdata['assigneemiddlename'] assigneelastname = requestdata['assigneelastname'] + statuslabel = requestdata['requeststatuslabel'] if int(requestid) and str(requestid) != "-1" : status = rawrequestservice().getstatus(updaterequest) - if status not in ['Intake in Progress', 'Closed', 'Redirect', 'Peer Review', 'Section 5 Pending', 'App Fee Owing']: + if statuslabel not in [StateName.intakeinprogress.name, StateName.closed.name, StateName.redirect.name, StateName.peerreview.name, StateName.section5pending.name, StateName.appfeeowing.name]: raise ValueError('Invalid request state.') - result = rawrequestservice().saverawrequestversion(updaterequest,requestid,assigneegroup,assignee,status,AuthHelper.getuserid(),assigneefirstname,assigneemiddlename,assigneelastname, actiontype) + result = rawrequestservice().saverawrequestversion(updaterequest,requestid,assigneegroup,assignee,status,AuthHelper.getuserid(),assigneefirstname,assigneemiddlename,assigneelastname, statuslabel, actiontype) assignee = '' if(actiontype == 'assignee'): assignee = getassignee(assigneefirstname,assigneelastname,assigneegroup) @@ -128,7 +130,8 @@ def getparams(updaterequest): 'assignee': updaterequest["assignedTo"] if 'assignedTo' in updaterequest else None, 'assigneefirstname': updaterequest["assignedToFirstName"] if updaterequest.get("assignedToFirstName") != None else None, 'assigneemiddlename': updaterequest["assignedToMiddleName"] if updaterequest.get("assignedToMiddleName") != None else None, - 'assigneelastname': updaterequest["assignedToLastName"] if updaterequest.get("assignedToLastName") != None else None + 'assigneelastname': updaterequest["assignedToLastName"] if updaterequest.get("assignedToLastName") != None else None, + 'requeststatuslabel': updaterequest["requeststatuslabel"] if updaterequest.get("requeststatuslabel") != None else None } @cors_preflight('GET,OPTIONS') diff --git a/request-management-api/request_api/schemas/foirequestwrapper.py b/request-management-api/request_api/schemas/foirequestwrapper.py index efdb027ac..ce3ef32f6 100644 --- a/request-management-api/request_api/schemas/foirequestwrapper.py +++ b/request-management-api/request_api/schemas/foirequestwrapper.py @@ -105,6 +105,7 @@ class Meta: # pylint: disable=too-few-public-methods 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) requeststatusid = fields.Int(data_key="requeststatusid",allow_none=True) + requeststatuslabel = fields.Str(data_key="requeststatuslabel",allow_none=False) closedate = fields.Date(data_key="closedate", required=False,allow_none=True) closereasonid = fields.Int(data_key="closereasonid",allow_none=True) correctionalServiceNumber = fields.Str(data_key="correctionalServiceNumber",allow_none=True, validate=[validate.Length(max=50, error=MAX_EXCEPTION_MESSAGE)]) @@ -168,6 +169,7 @@ class Meta: # pylint: disable=too-few-public-methods assignedgroup = fields.Str(data_key="assignedGroup",allow_none=True, validate=[validate.Length(max=250, error=MAX_EXCEPTION_MESSAGE)]) assignedto = fields.Str(data_key="assignedTo",allow_none=True, validate=[validate.Length(max=120, error=MAX_EXCEPTION_MESSAGE)]) requeststatusid = fields.Int(data_key="requeststatusid",allow_none=True) + requeststatuslabel = fields.Str(data_key="requeststatuslabel",allow_none=False) divisions = fields.Nested(FOIMinistryRequestDivisionSchema, many=True,allow_none=True) documents = fields.Nested(FOIMinistryRequestDocumentSchema, many=True,allow_none=True) assignedToFirstName = fields.Str(data_key="assignedToFirstName",allow_none=True, validate=[validate.Length(max=50, error=MAX_EXCEPTION_MESSAGE)]) diff --git a/request-management-api/request_api/services/events/state.py b/request-management-api/request_api/services/events/state.py index f317f6e7c..72cdaa439 100644 --- a/request-management-api/request_api/services/events/state.py +++ b/request-management-api/request_api/services/events/state.py @@ -9,6 +9,7 @@ from request_api.models.FOIRequestStatus import FOIRequestStatus import json from request_api.models.default_method_result import DefaultMethodResult +from request_api.utils.enums import StateName class stateevent: """ FOI Event management service @@ -34,12 +35,12 @@ def __haschanged(self, requestid, requesttype): if len(states) == 2: newstate = states[0] oldstate = states[1] - if newstate != oldstate and newstate != 'Intake in Progress': + if newstate != oldstate and newstate != StateName.intakeinprogress.value: return newstate return None def __createcommentwrapper(self, requestid, state, requesttype, userid, username): - if state == 'Archived': + if state == StateName.archived.value: _openedministries = FOIMinistryRequest.getministriesopenedbyuid(requestid) for ministry in _openedministries: response=self.__createcomment(ministry["ministryrequestid"], state, 'ministryrequest', userid, username) @@ -58,16 +59,17 @@ def __createcomment(self, requestid, state, requesttype, userid, username): def __createnotification(self, requestid, state, requesttype, userid): _notificationtype = "State" - if state == 'Call For Records' and requesttype == "ministryrequest": + if state == StateName.callforrecords.value and requesttype == "ministryrequest": foirequest = notificationservice().getrequest(requestid, requesttype) _notificationtype = "Group Members" if foirequest['assignedministryperson'] is None else "State" notification = self.__preparenotification(state) - if state == "Response" and requesttype == "ministryrequest": + if state == StateName.response.value and requesttype == "ministryrequest": signgoffapproval = FOIMinistryRequest().getrequest(requestid)['ministrysignoffapproval'] - notification = notification + f". Approved by {signgoffapproval['approvername']}, {signgoffapproval['approvertitle']} on {signgoffapproval['approveddate']}" - if state == 'Closed' or state == 'Archived' : + if signgoffapproval: + notification = notification + f". Approved by {signgoffapproval['approvername']}, {signgoffapproval['approvertitle']} on {signgoffapproval['approveddate']}" + if state == StateName.closed.value or state == StateName.archived.value: notificationservice().dismissnotificationsbyrequestid(requestid, requesttype) - if state == 'Archived': + if state == StateName.archived.value: _openedministries = FOIMinistryRequest.getministriesopenedbyuid(requestid) for ministry in _openedministries: response = notificationservice().createnotification({"message" : notification}, ministry["ministryrequestid"], 'ministryrequest', "State", userid) @@ -88,7 +90,7 @@ def __preparenotification(self, state): return self.__notificationmessage(state) def __preparegroupmembernotification(self, state, requestid): - if state == 'Call For Records': + if state == StateName.callforrecords.value: return self.__notificationcfrmessage(requestid) return self.__groupmembernotificationmessage(state) @@ -101,13 +103,14 @@ def __preparecomment(self, requestid, state,requesttype, username): return comment def __formatstate(self, state): - return "Open" if state == "Archived" else state + return StateName.open.value if state == StateName.archived.value else state def __commentmessage(self, state, username, requesttype, requestid): comment = username+' changed the state of the request to '+self.__formatstate(state) - if state == "Response" and requesttype == "ministryrequest": + if state == StateName.response.value and requesttype == "ministryrequest": signgoffapproval = FOIMinistryRequest().getrequest(requestid)['ministrysignoffapproval'] - comment = comment + f". Approved by {signgoffapproval['approvername']}, {signgoffapproval['approvertitle']} on {signgoffapproval['approveddate']}" + if signgoffapproval: + comment = comment + f". Approved by {signgoffapproval['approvername']}, {signgoffapproval['approvertitle']} on {signgoffapproval['approveddate']}" return comment def __notificationmessage(self, state): @@ -119,7 +122,7 @@ def __notificationcfrmessage(self, requestid): def __createcfrentry(self, state, ministryrequestid, userid): cfrfee = cfrfeeservice().getcfrfee(ministryrequestid) - if (state == "Fee Estimate" and cfrfee['cfrfeestatusid'] in (None, '')): + if (state == StateName.feeestimate.value and cfrfee['cfrfeestatusid'] in (None, '')): return cfrfeeservice().sanctioncfrfee(ministryrequestid, {"status": "review"}, userid) else: return DefaultMethodResult(True,'No action needed',ministryrequestid) diff --git a/request-management-api/request_api/services/foirequest/requestservicebuilder.py b/request-management-api/request_api/services/foirequest/requestservicebuilder.py index 4f6db7aa5..d3f5a4d8b 100644 --- a/request-management-api/request_api/services/foirequest/requestservicebuilder.py +++ b/request-management-api/request_api/services/foirequest/requestservicebuilder.py @@ -8,8 +8,9 @@ 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.FOIRequestStatus import FOIRequestStatus from datetime import datetime as datetime2 -from request_api.utils.enums import MinistryTeamWithKeycloackGroup +from request_api.utils.enums import MinistryTeamWithKeycloackGroup, StateName from request_api.services.foirequest.requestserviceconfigurator import requestserviceconfigurator from request_api.services.foirequest.requestserviceministrybuilder import requestserviceministrybuilder @@ -22,7 +23,8 @@ class requestservicebuilder(requestserviceconfigurator): def createministry(self, requestschema, ministry, activeversion, userid, filenumber=None, ministryid=None): foiministryrequest = FOIMinistryRequest() foiministryrequest.__dict__.update(ministry) - foiministryrequest.requeststatusid = requestschema.get("requeststatusid") + foiministryrequest.requeststatusid = self.__getrequeststatusid(requestschema.get("requeststatuslabel")) + foiministryrequest.requeststatuslabel = requestschema.get("requeststatuslabel") foiministryrequest.isactive = True foiministryrequest.axisrequestid = requestschema.get("axisRequestId") foiministryrequest.axissyncdate = requestschema.get("axisSyncDate") @@ -43,9 +45,9 @@ def createministry(self, requestschema, ministry, activeversion, userid, filenum startdate = requestschema.get("requestProcessStart") foiministryrequest.startdate = startdate foiministryrequest.createdby = userid - requeststatusid = self.getpropertyvaluefromschema(requestschema, 'requeststatusid') - if requeststatusid is not None: - status = self.getstatusname(requeststatusid) + requeststatuslabel = self.getpropertyvaluefromschema(requestschema, 'requeststatuslabel') + if requeststatuslabel is not None: + status = self.getstatusname(requeststatuslabel) if self.isNotBlankorNone(requestschema,"fromDate","main") == True: foiministryrequest.recordsearchfromdate = requestschema.get("fromDate") if self.isNotBlankorNone(requestschema,"toDate","main") == True: @@ -89,7 +91,7 @@ def __updateassignedtoandgroup(self, foiministryrequest, requestschema, ministry foiministryrequest.assignedto = None def __isgrouprequired(self,status): - if status == "Call For Records" or status == "Review" or status == "Consult" or status == "Fee Assessed" or status == "Ministry Sign Off" or status == "Response": + if status == StateName.callforrecords.value or status == StateName.recordsreview.value or status == StateName.consult.value or status == StateName.feeestimate.value or status == StateName.ministrysignoff.value or status == StateName.response.value: return True else: return False @@ -97,6 +99,17 @@ def __isgrouprequired(self,status): def __getgroupname(self, requesttype, bcgovcode): return 'Flex Team' if requesttype == "general" else FOIRequestTeam.getdefaultprocessingteamforpersonal(bcgovcode) + def __getrequeststatusid(self, requeststatuslabel): + state = FOIRequestStatus.getrequeststatusbylabel( + requeststatuslabel + ) + stateid = ( + state.get("requeststatusid") + if isinstance(state, dict) and state.get("requeststatusid") not in (None, "") + else "" + ) + return stateid + def createcontactinformation(self,dataformat, name, value, contacttypes, userid): contactinformation = FOIRequestContactInformation() contactinformation.contactinformation = value diff --git a/request-management-api/request_api/services/foirequest/requestserviceconfigurator.py b/request-management-api/request_api/services/foirequest/requestserviceconfigurator.py index a2a87909f..2c31f1674 100644 --- a/request-management-api/request_api/services/foirequest/requestserviceconfigurator.py +++ b/request-management-api/request_api/services/foirequest/requestserviceconfigurator.py @@ -15,10 +15,10 @@ class requestserviceconfigurator: """This class consolidates helper fiunctions and constants """ - def getstatusname(self,requeststatusid): + def getstatusname(self,requeststatuslabel): allstatus = FOIRequestStatus().getrequeststatuses() for status in allstatus: - if status["requeststatusid"] == requeststatusid: + if status["statuslabel"] == requeststatuslabel: return status["name"] return None; diff --git a/request-management-api/request_api/services/foirequest/requestservicecreate.py b/request-management-api/request_api/services/foirequest/requestservicecreate.py index 6d4b2142f..ac6f24275 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.utils.enums import StateName import json class requestservicecreate: @@ -169,10 +170,10 @@ def __prepareapplicants(self, foirequestschema, userid): return requestapplicantarr def __disablewatchers(self, ministryid, requestschema, userid): - requeststatusid = requestschema.get("requeststatusid") if 'requeststatusid' in requestschema else None - if requeststatusid is not None: - status = requestserviceconfigurator().getstatusname(requeststatusid) - if status == "Open": + requeststatuslabel = requestschema.get("requeststatuslabel") if 'requeststatuslabel' in requestschema else None + if requeststatuslabel is not None: + status = requestserviceconfigurator().getstatusname(requeststatuslabel) + if status == StateName.open.value: watchers = watcherservice().getministryrequestwatchers(int(ministryid), True) for watcher in watchers: watcherschema = {"ministryrequestid":ministryid,"watchedbygroup":watcher["watchedbygroup"],"watchedby":watcher["watchedby"],"isactive":False} diff --git a/request-management-api/request_api/services/foirequest/requestservicegetter.py b/request-management-api/request_api/services/foirequest/requestservicegetter.py index e5ae2c249..f8a7492c4 100644 --- a/request-management-api/request_api/services/foirequest/requestservicegetter.py +++ b/request-management-api/request_api/services/foirequest/requestservicegetter.py @@ -15,6 +15,7 @@ from request_api.services.programareaservice import programareaservice from request_api.utils.commons.datetimehandler import datetimehandler from request_api.services.external.keycloakadminservice import KeycloakAdminService +from request_api.utils.enums import StateName class requestservicegetter: """ This class consolidates retrival of FOI request for actors: iao and ministry. @@ -29,7 +30,7 @@ def getrequest(self,foirequestid,foiministryrequestid): iaorestrictrequestdetails = FOIRestrictedMinistryRequest.getrestricteddetails(ministryrequestid=foiministryrequestid,type='iao') baserequestinfo = self.__preparebaseinfo(request,foiministryrequestid,requestministry,requestministrydivisions) - baserequestinfo['lastStatusUpdateDate'] = FOIMinistryRequest.getLastStatusUpdateDate(foiministryrequestid, requestministry['requeststatus.requeststatusid']).strftime(self.__genericdateformat()), + baserequestinfo['lastStatusUpdateDate'] = FOIMinistryRequest.getLastStatusUpdateDate(foiministryrequestid, requestministry['requeststatuslabel']).strftime(self.__genericdateformat()), for contactinfo in requestcontactinformation: if contactinfo['contacttype.name'] == 'Email': baserequestinfo.update({'email':contactinfo['contactinformation']}) @@ -152,8 +153,8 @@ def __preparebaseinfo(self,request,foiministryrequestid,requestministry,requestm 'description': requestministry['description'], 'fromDate': parse(requestministry['recordsearchfromdate']).strftime(self.__genericdateformat()) if requestministry['recordsearchfromdate'] is not None else '', 'toDate': parse(requestministry['recordsearchtodate']).strftime(self.__genericdateformat()) if requestministry['recordsearchtodate'] is not None else '', - 'currentState':requestministry['requeststatus.name'], - 'requeststatusid':requestministry['requeststatus.requeststatusid'], + 'currentState':requestministry['requeststatus.name'], + 'requeststatuslabel':requestministry['requeststatuslabel'], 'requestProcessStart': parse(requestministry['startdate']).strftime(self.__genericdateformat()) if requestministry['startdate'] is not None else '', 'dueDate':parse(requestministry['duedate']).strftime(self.__genericdateformat()), 'originalDueDate': parse(requestministry['originalldd']).strftime(self.__genericdateformat()) if requestministry['originalldd'] is not None else parse(requestministry['duedate']).strftime(self.__genericdateformat()), @@ -213,7 +214,7 @@ def getonholdtransition(self, foiministryrequestid): onholddate = None transitions = FOIMinistryRequest.getrequeststatusById(foiministryrequestid) for entry in transitions: - if entry['requeststatusid'] == 11: + if entry['requeststatuslabel'] == StateName.onhold.name: onholddate = datetimehandler().convert_to_pst(entry['created_at'],'%Y-%m-%d') else: if onholddate is not 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..56db80d2d 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.FOIRequestStatus import FOIRequestStatus from request_api.services.foirequest.requestserviceconfigurator import requestserviceconfigurator from datetime import datetime as datetime2 @@ -76,7 +77,8 @@ def createfoiministryrequestfromobject(self, ministryschema, requestschema, user foiministryrequest.assignedto = None if usertype == "iao" and 'assignedto' in requestschema and requestschema['assignedto'] in (None, '') else ministryschema["assignedto"] foiministryrequest.ministrysignoffapproval = requestdict["ministrysignoffapproval"] - foiministryrequest.requeststatusid = requestdict['requeststatusid'] + foiministryrequest.requeststatusid = self.__getrequeststatusid(requestdict['requeststatuslabel']) + foiministryrequest.requeststatuslabel = requestdict['requeststatuslabel'] foiministryrequest.programareaid = requestdict['programareaid'] foiministryrequest.createdby = userid @@ -88,6 +90,16 @@ def createfoiministryrequestfromobject(self, ministryschema, requestschema, user foiministryrequest.closereasonid = requestdict['closereasonid'] return foiministryrequest + def __getrequeststatusid(self, requeststatuslabel): + state = FOIRequestStatus.getrequeststatusbylabel( + requeststatuslabel + ) + stateid = ( + state.get("requeststatusid") + if isinstance(state, dict) and state.get("requeststatusid") not in (None, "") + else "" + ) + return stateid def __createministrydivisions(self, requestschema, foiministryrequestid, foiministryrequestversion, userid): if 'divisions' in requestschema: return self.createfoirequestdivision(requestschema,foiministryrequestid ,foiministryrequestversion + 1, userid) @@ -111,7 +123,7 @@ def createfoiministryrequestfromobject1(self, ministryschema, requestschema): 'duedate': requestschema['duedate'] if 'duedate' in requestschema else ministryschema["duedate"], #and isextension':= True 'assignedministrygroup': requestschema['assignedministrygroup'] if 'assignedministrygroup' in requestschema else ministryschema["assignedministrygroup"], 'assignedgroup': requestschema['assignedgroup'] if 'assignedgroup' in requestschema else ministryschema["assignedgroup"], - 'requeststatusid': requestschema['requeststatusid'] if 'requeststatusid' in requestschema else ministryschema["requeststatus.requeststatusid"], + 'requeststatuslabel': requestschema['requeststatuslabel'] if 'requeststatuslabel' in requestschema else ministryschema["requeststatuslabel"], 'programareaid': ministryschema["programarea.programareaid"] if 'programarea.programareaid' in ministryschema else None, 'closedate': requestschema['closedate'] if 'closedate' in requestschema else None, 'closereasonid': requestschema['closereasonid'] if 'closereasonid' in requestschema else None, diff --git a/request-management-api/request_api/services/foirequest/requestserviceupdate.py b/request-management-api/request_api/services/foirequest/requestserviceupdate.py index c800ae387..a85ca38e9 100644 --- a/request-management-api/request_api/services/foirequest/requestserviceupdate.py +++ b/request-management-api/request_api/services/foirequest/requestserviceupdate.py @@ -19,7 +19,7 @@ def updaterequest(self,foirequestschema,foirequestid,userid): for ministry in foirequestschema.get("selectedMinistries"): for status in allstatus: if ministry["status"] == status["name"]: - updatedministries.append({"filenumber" : ministry["filenumber"], "requeststatusid": status["requeststatusid"]}) + updatedministries.append({"filenumber" : ministry["filenumber"], "requeststatuslabel": status["statuslabel"]}) return FOIRequest.updateStatus(foirequestid, updatedministries, userid) def updateministryrequestduedate(self, ministryrequestid, duedate, userid): diff --git a/request-management-api/request_api/services/rawrequest/rawrequestservicegetter.py b/request-management-api/request_api/services/rawrequest/rawrequestservicegetter.py index bb56f9317..b8b1cf870 100644 --- a/request-management-api/request_api/services/rawrequest/rawrequestservicegetter.py +++ b/request-management-api/request_api/services/rawrequest/rawrequestservicegetter.py @@ -7,6 +7,7 @@ from dateutil.parser import parse import maya from request_api.models.FOIAssignees import FOIAssignee +from request_api.utils.enums import StateName class rawrequestservicegetter: """ This class consolidates retrival of FOI raw request for actors: iao. @@ -52,7 +53,7 @@ def getallrawrequests(self): def getrawrequestforid(self, requestid): request = FOIRawRequest.get_request(requestid) request = self.__attachministriesinfo(request) - if request != {} and (request['version'] == 1 or request['status'] == 'Unopened') and request['sourceofsubmission'] != "intake": + if request != {} and (request['version'] == 1 or request['status'] == StateName.unopened.value) and request['sourceofsubmission'] != "intake": requestrawdata = request['requestrawdata'] requesttype = requestrawdata['requestType']['requestType'] baserequestinfo = self.__preparebaserequestinfo(requestid, request, requesttype, requestrawdata) @@ -60,16 +61,15 @@ def getrawrequestforid(self, requestid): baserequestinfo['additionalPersonalInfo'] = self.__prepareadditionalpersonalinfo(requestrawdata) return baserequestinfo elif request != {} and request['version'] != 1 and request['sourceofsubmission'] != "intake": - request['requestrawdata']['currentState'] = request['status'] - requeststatus = FOIRequestStatus().getrequeststatusid(request['status']) - request['requestrawdata']['requeststatusid'] = requeststatus['requeststatusid'] + request['requestrawdata']['currentState'] = request['status'] + request['requestrawdata']['requeststatuslabel'] = request['requeststatuslabel'] request['requestrawdata']['lastStatusUpdateDate'] = FOIRawRequest.getLastStatusUpdateDate(requestid, request['status']).strftime(self.__generaldateformat()) - if request['status'] == 'Closed': + if request['requeststatuslabel'] == StateName.closed.name: request['requestrawdata']['stateTransition']= FOIRawRequest.getstatesummary(requestid) request['requestrawdata']['wfinstanceid'] = request['wfinstanceid'] request['requestrawdata']['closedate']= self.__getclosedate(request['closedate']) request['requestrawdata']['isiaorestricted']= request['isiaorestricted'] if request['isiaorestricted'] is not None else False - return request['requestrawdata'] + return request['requestrawdata'] elif request != {} and request['sourceofsubmission'] == "intake": requestrawdata = request['requestrawdata'] requesttype = requestrawdata['requestType'] @@ -81,8 +81,8 @@ def getrawrequestforid(self, requestid): request['requestrawdata']['wfinstanceid'] = request['wfinstanceid'] request['requestrawdata']['currentState'] = request['status'] - requeststatus = FOIRequestStatus().getrequeststatusid(request['status']) - request['requestrawdata']['requeststatusid'] = requeststatus['requeststatusid'] + requeststatus = FOIRequestStatus().getrequeststatus(request['status']) + request['requestrawdata']['requeststatuslabel'] = requeststatus['statuslabel'] request['requestrawdata']['lastStatusUpdateDate'] = FOIRawRequest.getLastStatusUpdateDate(requestid, request['status']).strftime(self.__generaldateformat()) request['requestrawdata']['stateTransition']= FOIRawRequest.getstatesummary(requestid) request['requestrawdata']['closedate']= self.__getclosedate(request['closedate']) diff --git a/request-management-api/request_api/services/rawrequestservice.py b/request-management-api/request_api/services/rawrequestservice.py index 6abaf1ff1..1c0564733 100644 --- a/request-management-api/request_api/services/rawrequestservice.py +++ b/request-management-api/request_api/services/rawrequestservice.py @@ -15,7 +15,8 @@ from request_api.exceptions import BusinessException, Error from request_api.models.default_method_result import DefaultMethodResult from request_api.models.FOIRawRequestWatchers import FOIRawRequestWatcher -from request_api.services.foirequest.requestserviceconfigurator import requestserviceconfigurator +from request_api.services.foirequest.requestserviceconfigurator import requestserviceconfigurator +from request_api.utils.enums import StateName import logging class rawrequestservice: @@ -91,13 +92,13 @@ def doesrequirepayment(requestdatajson): return requestdatajson['requiresPayment'] raise BusinessException(Error.DATA_NOT_FOUND) - def saverawrequestversion(self, _requestdatajson, _requestid, _assigneegroup, _assignee, status, userid, assigneefirstname, assigneemiddlename, assigneelastname, actiontype=None): + def saverawrequestversion(self, _requestdatajson, _requestid, _assigneegroup, _assignee, status, userid, assigneefirstname, assigneemiddlename, assigneelastname, statuslabel, actiontype=None): ispiiredacted = _requestdatajson["ispiiredacted"] if 'ispiiredacted' in _requestdatajson else False #Get documents if actiontype == "assignee": result = FOIRawRequest.saverawrequestassigneeversion(_requestid, _assigneegroup, _assignee, userid, assigneefirstname, assigneemiddlename, assigneelastname) else: - result = FOIRawRequest.saverawrequestversion(_requestdatajson, _requestid, _assigneegroup, _assignee, status,ispiiredacted, userid, assigneefirstname, assigneemiddlename, assigneelastname) + result = FOIRawRequest.saverawrequestversion(_requestdatajson, _requestid, _assigneegroup, _assignee, status,ispiiredacted, userid, statuslabel, assigneefirstname, assigneemiddlename, assigneelastname) documentservice().createrawrequestdocumentversion(_requestid) return result @@ -125,10 +126,10 @@ def getrawrequestfields(self, requestid, fields): return rawrequestservicegetter().getrawrequestfieldsforid(requestid, fields) def getstatus(self, foirequest): - statusid = foirequest["requeststatusid"] if "requeststatusid" in foirequest else None - if statusid is not None: + statuslabel = foirequest["requeststatuslabel"] if "requeststatuslabel" in foirequest else None + if statuslabel is not None: try: - return requestserviceconfigurator().getstatusname(statusid) + return requestserviceconfigurator().getstatusname(statuslabel) # if statusid== 4: # return 'Redirect' # if statusid == 3: @@ -137,7 +138,7 @@ def getstatus(self, foirequest): # return 'Peer Review' except KeyError: print("Key Error on requeststatusid, ignore will be intake in Progress") - return 'Intake in Progress' + return StateName.intakeinprogress.value def getaxisequestids(self): return rawrequestservicegetter().getaxisequestids() diff --git a/request-management-api/request_api/services/requestservice.py b/request-management-api/request_api/services/requestservice.py index d98d24cb3..445ec9914 100644 --- a/request-management-api/request_api/services/requestservice.py +++ b/request-management-api/request_api/services/requestservice.py @@ -62,8 +62,8 @@ def saverequest( ) def saverequestversion(self, foirequestschema, foirequestid, ministryid, userid): - nextstate = FOIRequestStatus.getrequeststatusname( - foirequestschema["requeststatusid"] + nextstate = FOIRequestStatus.getrequeststatusbylabel( + foirequestschema["requeststatuslabel"] ) nextstatename = ( nextstate.get("name") @@ -112,8 +112,8 @@ def postpaymentstatetransition( foirequest = self.updateduedate( requestid, ministryrequestid, paymentdate, _foirequest, nextstatename ) - status = FOIRequestStatus().getrequeststatusid(nextstatename) - foirequest["requeststatusid"] = status["requeststatusid"] + status = FOIRequestStatus().getrequeststatus(nextstatename) + foirequest["requeststatuslabel"] = status["statuslabel"] return requestservicecreate().saverequestversion( foirequest, requestid, ministryrequestid, "Online Payment" ) @@ -204,7 +204,7 @@ def copysubjectcode(self, subjectcode, ministries, userid): def postopeneventtoworkflow(self, id, requestschema, ministries): pid = workflowservice().syncwfinstance("rawrequest", requestschema["id"]) - workflowservice().postunopenedevent(id, pid, requestschema, "Open", ministries) + workflowservice().postunopenedevent(id, pid, requestschema, StateName.open.value, ministries) def postfeeeventtoworkflow( self, requestid, ministryrequestid, paymentstatus, nextstatename=None @@ -215,14 +215,14 @@ def postfeeeventtoworkflow( ) def posteventtoworkflow(self, id, requestschema, data, usertype): - requeststatusid = ( - requestschema.get("requeststatusid") - if "requeststatusid" in requestschema + requeststatuslabel = ( + requestschema.get("requeststatuslabel") + if "requeststatuslabel" in requestschema else None ) status = ( - requestserviceconfigurator().getstatusname(requeststatusid) - if requeststatusid is not None + requestserviceconfigurator().getstatusname(requeststatuslabel) + if requeststatuslabel is not None else None ) pid = workflowservice().syncwfinstance("ministryrequest", id) diff --git a/request-management-api/request_api/services/workflowservice.py b/request-management-api/request_api/services/workflowservice.py index f4b6f81a0..1cbcbb1db 100644 --- a/request-management-api/request_api/services/workflowservice.py +++ b/request-management-api/request_api/services/workflowservice.py @@ -70,7 +70,7 @@ def postopenedevent(self, id, wfinstanceid, requestsschema, data, newstatus, use _variables = bpmservice().getinstancevariables(wfinstanceid) if ministry["status"] == OpenedEvent.callforrecords.value and (("status" not in _variables) or (_variables not in (None, []) and "status" in _variables and _variables["status"]["value"] != OpenedEvent.callforrecords.value)): messagename = MessageType.iaoopencomplete.value - elif _variables not in (None, []) and ("status" in _variables and _variables["status"]["value"] == "Closed"): + elif _variables not in (None, []) and ("status" in _variables and _variables["status"]["value"] == StateName.closed.value): return bpmservice().reopenevent(wfinstanceid, metadata, MessageType.iaoreopen.value) else: return bpmservice().openedcomplete(wfinstanceid, filenumber, metadata, messagename) diff --git a/request-management-api/request_api/utils/enums.py b/request-management-api/request_api/utils/enums.py index f21d807ab..becdb9d9e 100644 --- a/request-management-api/request_api/utils/enums.py +++ b/request-management-api/request_api/utils/enums.py @@ -149,15 +149,20 @@ class StateName(Enum): redirect = "Redirect" unopened = "Unopened" intakeinprogress = "Intake in Progress" - recordsreview = "Records Review" - feeestimate = "Fee Estimate" consult = "Consult" ministrysignoff = "Ministry Sign Off" onhold = "On Hold" deduplication = "Deduplication" harmsassessment = "Harms Assessment" response = "Response" - + feeestimate = "Fee Estimate" + recordsreview = "Records Review" + archived = "Archived" + peerreview = "Peer Review" + tagging = "Tagging" + readytoscan = "Ready to Scan" + appfeeowing = "App Fee Owing" + section5pending = "Section 5 Pending" class CacheUrls(Enum): keycloakusers= "/api/foiassignees" programareas= "/api/foiflow/programareas" From d871ad6f552f6ebadfa18afe6d647dab2f35ce37 Mon Sep 17 00:00:00 2001 From: Richard Qi Date: Mon, 27 Nov 2023 15:58:53 -0800 Subject: [PATCH 15/22] mute notifications for mcf #4548 --- .../request_api/services/notifications/notificationconfig.py | 4 ++++ .../request_api/services/notificationservice.py | 1 + 2 files changed, 5 insertions(+) diff --git a/request-management-api/request_api/services/notifications/notificationconfig.py b/request-management-api/request_api/services/notifications/notificationconfig.py index e00fe0f62..744ab450c 100644 --- a/request-management-api/request_api/services/notifications/notificationconfig.py +++ b/request-management-api/request_api/services/notifications/notificationconfig.py @@ -32,7 +32,11 @@ def getnotificationdays(self): return str(14) def getmutenotifications(self): +<<<<<<< HEAD if 'MUTE_NOTIFICATION' in os.environ and os.getenv('MUTE_NOTIFICATION') != '': +======= + if 'MUTE_NOTIFICATION' in os.environ: +>>>>>>> 21ce0b5a5 (mute notifications for mcf #4548) return json.loads(os.getenv('MUTE_NOTIFICATION')) else: 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 08d4f8c76..a63e30d5a 100644 --- a/request-management-api/request_api/services/notificationservice.py +++ b/request-management-api/request_api/services/notificationservice.py @@ -296,6 +296,7 @@ def __preparenotificationuser(self, requesttype, notificationuser, userid, mute= user.isdeleted = False else: user = FOIRawRequestNotificationUser() + user.isdeleted = False user.notificationusertypelabel = notificationuser["usertype"] user.userid = notificationuser["userid"] user.createdby = userid From a2a9803b395b1bfb8d5b13de42b673a4727c3a19 Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Tue, 21 Nov 2023 15:40:30 -0800 Subject: [PATCH 16/22] Fix indent --- .../FOI/FOIRequest/MinistryReview/MinistryReview.js | 7 +++++++ 1 file changed, 7 insertions(+) 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..d84998e69 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js @@ -436,10 +436,17 @@ const MinistryReview = React.memo(({ userDetail }) => { break; case StateEnum.tagging.name: foitabheaderBG = "foitabheadercollection foitabheaderTaggingBG"; +<<<<<<< HEAD break; case StateEnum.readytoscan.name: foitabheaderBG = "foitabheadercollection foitabheaderReadytoScanBG"; break; +======= + break; + case StateEnum.readytoscan.name: + foitabheaderBG = "foitabheadercollection foitabheaderReadytoScanBG"; + break; +>>>>>>> 421e4767c (Fix indent) default: foitabheaderBG = "foitabheadercollection foitabheaderdefaultBG"; break; From 6128e783594d27ecad5d311af8784b022c02ab7a Mon Sep 17 00:00:00 2001 From: Milos Despotovic Date: Tue, 21 Nov 2023 15:41:53 -0800 Subject: [PATCH 17/22] Remove whitespace --- .../FOI/FOIRequest/MinistryReview/MinistryReview.js | 7 ------- 1 file changed, 7 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 d84998e69..c6032e05e 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js @@ -436,17 +436,10 @@ const MinistryReview = React.memo(({ userDetail }) => { break; case StateEnum.tagging.name: foitabheaderBG = "foitabheadercollection foitabheaderTaggingBG"; -<<<<<<< HEAD - break; - case StateEnum.readytoscan.name: - foitabheaderBG = "foitabheadercollection foitabheaderReadytoScanBG"; - break; -======= break; case StateEnum.readytoscan.name: foitabheaderBG = "foitabheadercollection foitabheaderReadytoScanBG"; break; ->>>>>>> 421e4767c (Fix indent) default: foitabheaderBG = "foitabheadercollection foitabheaderdefaultBG"; break; From d41dee492a5754e538281d10146b591fd5b8cc8d Mon Sep 17 00:00:00 2001 From: Richard Qi Date: Wed, 29 Nov 2023 00:30:07 -0800 Subject: [PATCH 18/22] bug fix: new comment notification not checking isdeleted --- .../request_api/models/FOIRequestNotifications.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/request-management-api/request_api/models/FOIRequestNotifications.py b/request-management-api/request_api/models/FOIRequestNotifications.py index e4b767c6b..3ee391f39 100644 --- a/request-management-api/request_api/models/FOIRequestNotifications.py +++ b/request-management-api/request_api/models/FOIRequestNotifications.py @@ -68,9 +68,9 @@ def getconsolidatednotifications(cls, userid, days): notifications = [] try: sql = """select idnumber, axisnumber, notificationid, notification , notificationtype, userid, notificationusertype, created_at, createdby, requesttype, requestid, foirequestid from ( - select frn.idnumber, frn.axisnumber, frn.requestid, frns.notificationuserid as notificationid, 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 inner join "NotificationTypes" nty on frn.notificationtypelabel = nty.notificationtypelabel inner join "NotificationUserTypes" ntu on frns.notificationusertypelabel = ntu.notificationusertypelabel where frns.userid=:userid and frns.isdeleted = false and frn.created_at >= current_date - interval :days day + select frn.idnumber, frn.axisnumber, frn.requestid, frns.notificationuserid as notificationid, 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 frns.userid=:userid and frn.created_at >= current_date - interval :days day union all - select frn.idnumber, frn.axisnumber, frn.requestid, frns.notificationuserid as notificationid, 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 inner join "NotificationTypes" nty on frn.notificationtypelabel = nty.notificationtypelabel inner join "NotificationUserTypes" ntu on frns.notificationusertypelabel = ntu.notificationusertypelabel where frns.userid=:userid and frns.isdeleted = false and frn.created_at >= current_date - interval :days day + select frn.idnumber, frn.axisnumber, frn.requestid, frns.notificationuserid as notificationid, 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 frns.userid=:userid and frn.created_at >= current_date - interval :days day ) as notf order by created_at desc""" rs = db.session.execute(text(sql), {'userid': userid, 'days': days}) for row in rs: From 7a79e8dad3cac96dce90329aa485dd6229f64e42 Mon Sep 17 00:00:00 2001 From: Richard Qi Date: Wed, 29 Nov 2023 13:38:18 -0800 Subject: [PATCH 19/22] add mute to notification manager --- .../notification_api/services/notificationservice.py | 2 +- notification-manager/sample.env | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/notification-manager/notification_api/services/notificationservice.py b/notification-manager/notification_api/services/notificationservice.py index d4871ce3f..88361536f 100644 --- a/notification-manager/notification_api/services/notificationservice.py +++ b/notification-manager/notification_api/services/notificationservice.py @@ -102,4 +102,4 @@ def __mutenotification(self, requesttype, notificationtype, request): return False return True - return False \ No newline at end of file + return False diff --git a/notification-manager/sample.env b/notification-manager/sample.env index 8898ee81e..ec3d90c8a 100644 --- a/notification-manager/sample.env +++ b/notification-manager/sample.env @@ -19,4 +19,4 @@ NOTIFICATION_REDIS_PORT= NOTIFICATION_REDIS_PASSWORD= NOTIFICATION_REDIS_HEALTHCHECK_INT=10 NOTIFICATION_STREAM_KEY=FOINOTIFICATION -MUTE_NOTIFICATION={"MCF": {"request_types": ["Personal"], "state_exceptions": ["Call For Records", "Ministry Sign Off"], "type_exceptions":["Reply User Comments", "Tagged User Comments"]}} \ No newline at end of file +MUTE_NOTIFICATION={"MCF": {"request_types": ["Personal"], "state_exceptions": ["Call For Records", "Ministry Sign Off"], "type_exceptions":["Reply User Comments", "Tagged User Comments"]}} From 825bccd78938e1c26f73f8108c056a7f5c5a2449 Mon Sep 17 00:00:00 2001 From: Shivakumar Date: Mon, 11 Dec 2023 10:59:14 -0800 Subject: [PATCH 20/22] Refacoring status labels for notifications --- .../dao/models/FOIRequestNotificationUsers.py | 5 +++-- .../notifications/notificationconfig.py | 2 +- .../notifications/notificationuser.py | 14 ++++++------- .../common/notificationusertypes.json | 21 +++++++++++++++++++ .../migrations/versions/29b44e8dc305_.py | 4 ++++ .../models/FOIRawRequestNotificationUsers.py | 14 ++++++++----- .../models/FOIRawRequestNotifications.py | 2 +- .../models/FOIRequestNotificationUsers.py | 4 ++-- .../models/FOIRequestNotifications.py | 14 ++++++------- .../models/NotificationUserTypes.py | 9 +++++++- .../notifications/notificationconfig.py | 18 ++++++++++++++-- .../notifications/notificationuser.py | 14 ++++++------- .../services/notificationservice.py | 2 ++ 13 files changed, 88 insertions(+), 35 deletions(-) diff --git a/notification-manager/notification_api/dao/models/FOIRequestNotificationUsers.py b/notification-manager/notification_api/dao/models/FOIRequestNotificationUsers.py index b1c688834..ecf341c6f 100644 --- a/notification-manager/notification_api/dao/models/FOIRequestNotificationUsers.py +++ b/notification-manager/notification_api/dao/models/FOIRequestNotificationUsers.py @@ -11,7 +11,8 @@ class Meta: # pylint: disable=too-few-public-methods unknown = EXCLUDE notificationid = fields.Int(data_key="notificationid") userid = fields.Str(data_key="userid") - notificationusertypelabel = fields.Int(data_key="notificationusertypelabel") + notificationusertypelabel = fields.Str(data_key="notificationusertypelabel") + notificationusertypeid = fields.Int(data_key="notificationusertypeid") createdby = fields.Str(data_key="createdby") created_at = fields.Str(data_key="created_at") isdeleted = fields.Boolean(data_key="isdeleted") @@ -22,7 +23,7 @@ def savenotificationuser(self, notificationuser): conn = getconnection() cursor = conn.cursor() cursor.execute('INSERT INTO public."FOIRequestNotificationUsers" (notificationid, userid, notificationusertypeid, notificationusertypelabel, createdby, created_at, isdeleted) \ - VALUES(%s::integer, %s, %s::integer, %s, %s, %s::boolean)', + VALUES(%s::integer, %s, %s::integer, %s, %s, %s, %s::boolean)', (int(notificationuser.notificationid), str(notificationuser.userid), int(notificationuser.notificationusertypeid), str(notificationuser.notificationusertypelabel), str(notificationuser.createdby), datetime.now(), int(notificationuser.isdeleted))) conn.commit() cursor.close() diff --git a/notification-manager/notification_api/services/notifications/notificationconfig.py b/notification-manager/notification_api/services/notifications/notificationconfig.py index e6be3ef60..4c6ed8179 100644 --- a/notification-manager/notification_api/services/notifications/notificationconfig.py +++ b/notification-manager/notification_api/services/notifications/notificationconfig.py @@ -16,7 +16,7 @@ def getnotificationtypeid(self, notificationtype): if notificationid is not None: return notificationid - def getnotificationusertypeid(self, notificationusertype): + def getnotficationusertypelabel(self, notificationusertype): notificationuserid = NotificationUserType().getid(notificationusertype) if notificationuserid is not None: return notificationuserid diff --git a/notification-manager/notification_api/services/notifications/notificationuser.py b/notification-manager/notification_api/services/notifications/notificationuser.py index 974930cc5..49e02c48a 100644 --- a/notification-manager/notification_api/services/notifications/notificationuser.py +++ b/notification-manager/notification_api/services/notifications/notificationuser.py @@ -54,26 +54,26 @@ def __istaggeduser(self, notificationuser, foicomment, notificationtype): def __gettriggereduser(self, userid, notificationtype): notificationusers = [] if notificationtype in ["Records", "PDFStitch"]: - notificationusers.append({"userid":userid, "usertype":notificationconfig().getnotificationusertypeid("triggered user")}) + notificationusers.append({"userid":userid, "usertype":notificationconfig().getnotficationusertypelabel("triggered user")}) return notificationusers def __getwatchers(self, notificationtype, foirequest, requesttype, requestjson=None): notificationusers = [] if notificationtype == "Watcher": - notificationusers.append({"userid": requestjson['watchedby'], "usertype":notificationconfig().getnotificationusertypeid("Watcher")}) + notificationusers.append({"userid": requestjson['watchedby'], "usertype":notificationconfig().getnotficationusertypelabel("Watcher")}) 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().getnotificationusertypeid("Watcher")}) + notificationusers.append({"userid":watcher["watchedby"], "usertype":notificationconfig().getnotficationusertypelabel("Watcher")}) return notificationusers def __getassignees(self, foirequest, requesttype, notificationtype, requestjson=None): notificationusers = [] - notificationtypelabel = notificationconfig().getnotificationusertypeid("Assignee") + notificationtypelabel = notificationconfig().getnotficationusertypelabel("Assignee") if notificationtype == 'User Assignment Removal': notificationusers.append({"userid": requestjson['userid'], "usertype":notificationtypelabel}) else: @@ -105,7 +105,7 @@ def __getcommentusertype(self, userid, requestusers): for requestuser in requestusers: if requestuser["userid"] == userid: return requestuser["usertype"] - return notificationconfig().getnotificationusertypeid("comment user") + return notificationconfig().getnotficationusertypelabel("comment user") def __getrelatedusers(self, comment, requesttype): if requesttype == "ministryrequest": @@ -121,12 +121,12 @@ def __gettaggedusers(self, comment): def __preparetaggeduser(self, data): taggedusers = [] for entry in data: - taggedusers.append({"userid":entry["username"], "usertype":notificationconfig().getnotificationusertypeid("comment tagged user")}) + taggedusers.append({"userid":entry["username"], "usertype":notificationconfig().getnotficationusertypelabel("comment tagged user")}) return taggedusers def __getgroupmembers(self,groupid): notificationusers = [] - notificationtypelabel = notificationconfig().getnotificationusertypeid("Group Members") + notificationtypelabel = notificationconfig().getnotficationusertypelabel("Group Members") usergroupfromkeycloak= KeycloakAdminService().getmembersbygroupname(groupid) for user in usergroupfromkeycloak[0].get("members"): notificationusers.append({"userid":user["username"], "usertype":notificationtypelabel}) diff --git a/request-management-api/common/notificationusertypes.json b/request-management-api/common/notificationusertypes.json index 0ea835c44..db1796c0e 100644 --- a/request-management-api/common/notificationusertypes.json +++ b/request-management-api/common/notificationusertypes.json @@ -13,6 +13,27 @@ "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", diff --git a/request-management-api/migrations/versions/29b44e8dc305_.py b/request-management-api/migrations/versions/29b44e8dc305_.py index cb7400207..f940d1dcc 100644 --- a/request-management-api/migrations/versions/29b44e8dc305_.py +++ b/request-management-api/migrations/versions/29b44e8dc305_.py @@ -31,18 +31,22 @@ def upgrade(): op.execute('ALTER TABLE public."FOIRequestNotifications" ADD COLUMN notificationtypelabel VARCHAR(50);') op.execute('UPDATE public."FOIRequestNotifications" AS mr SET notificationtypelabel = st.notificationtypelabel FROM public."NotificationTypes" AS st WHERE mr.notificationtypeid = st.notificationtypeid;') op.execute('ALTER TABLE public."FOIRequestNotifications" ALTER COLUMN notificationtypelabel SET NOT NULL;') + op.execute('ALTER TABLE public."FOIRequestNotifications" ALTER COLUMN notificationtypeid DROP NOT NULL;') op.execute('ALTER TABLE public."FOIRawRequestNotifications" ADD COLUMN notificationtypelabel VARCHAR(50);') op.execute('UPDATE public."FOIRawRequestNotifications" AS mr SET notificationtypelabel = st.notificationtypelabel FROM public."NotificationTypes" AS st WHERE mr.notificationtypeid = st.notificationtypeid;') op.execute('ALTER TABLE public."FOIRawRequestNotifications" ALTER COLUMN notificationtypelabel SET NOT NULL;') + op.execute('ALTER TABLE public."FOIRawRequestNotifications" ALTER COLUMN notificationtypeid DROP NOT NULL;') op.execute('ALTER TABLE public."FOIRequestNotificationUsers" ADD COLUMN notificationusertypelabel VARCHAR(50);') op.execute('UPDATE public."FOIRequestNotificationUsers" AS mr SET notificationusertypelabel = st.notificationusertypelabel FROM public."NotificationUserTypes" AS st WHERE mr.notificationusertypeid = st.notificationusertypeid;') op.execute('ALTER TABLE public."FOIRequestNotificationUsers" ALTER COLUMN notificationusertypelabel SET NOT NULL;') + op.execute('ALTER TABLE public."FOIRequestNotificationUsers" ALTER COLUMN notificationusertypelabel DROP NOT NULL;') op.execute('ALTER TABLE public."FOIRawRequestNotificationUsers" ADD COLUMN notificationusertypelabel VARCHAR(50);') op.execute('UPDATE public."FOIRawRequestNotificationUsers" AS mr SET notificationusertypelabel = st.notificationusertypelabel FROM public."NotificationUserTypes" AS st WHERE mr.notificationusertypeid = st.notificationusertypeid;') op.execute('ALTER TABLE public."FOIRawRequestNotificationUsers" ALTER COLUMN notificationusertypelabel SET NOT NULL;') + op.execute('ALTER TABLE public."FOIRawRequestNotificationUsers" ALTER COLUMN notificationusertypelabel DROP NOT NULL;') # ### end Alembic commands ### diff --git a/request-management-api/request_api/models/FOIRawRequestNotificationUsers.py b/request-management-api/request_api/models/FOIRawRequestNotificationUsers.py index 8094f76c3..9fabc6c6d 100644 --- a/request-management-api/request_api/models/FOIRawRequestNotificationUsers.py +++ b/request-management-api/request_api/models/FOIRawRequestNotificationUsers.py @@ -17,7 +17,8 @@ from request_api.utils.enums import ProcessingTeamWithKeycloackGroup, IAOTeamWithKeycloackGroup from request_api.models.views.FOINotifications import FOINotifications from request_api.models.views.FOIRawRequests import FOIRawRequests - +f = open('common/notificationusertypes.json', encoding="utf8") +notificationusertypes_cache = json.load(f) class FOIRawRequestNotificationUser(db.Model): # Name of the table in our database @@ -31,8 +32,8 @@ class FOIRawRequestNotificationUser(db.Model): createdby = db.Column(db.String(120), unique=False, nullable=True) updated_at = db.Column(db.DateTime, nullable=True) updatedby = db.Column(db.String(120), unique=False, nullable=True) - - notificationusertypelabel = db.Column(db.Integer,nullable=False) + notificationusertypeid = db.Column(db.Integer,nullable=False) + notificationusertypelabel = db.Column(db.String(120),nullable=False) @classmethod @@ -92,7 +93,10 @@ def getnotificationsbyuser(cls, userid): return notifications @classmethod - def getnotificationsbyuserandtype(cls, userid, notificationusertypelabel): + 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 notifications = [] try: sql = """select notificationid, count(1) as relcount from "FOIRawRequestNotificationUsers" frnu @@ -263,4 +267,4 @@ def validatefield(cls, x): class FOIRawRequestNotificationUserSchema(ma.Schema): class Meta: - fields = ('notificationid', 'userid','notificationusertypelabel','created_at','createdby','updated_at','updatedby') \ No newline at end of file + fields = ('notificationid', 'userid', 'notificationusertypeid' , 'notificationusertypelabel','created_at','createdby','updated_at','updatedby') \ No newline at end of file diff --git a/request-management-api/request_api/models/FOIRawRequestNotifications.py b/request-management-api/request_api/models/FOIRawRequestNotifications.py index 248e29c18..4104b90ec 100644 --- a/request-management-api/request_api/models/FOIRawRequestNotifications.py +++ b/request-management-api/request_api/models/FOIRawRequestNotifications.py @@ -115,4 +115,4 @@ def getnotificationidsbytype(cls, notificationtypelabel): class FOIRawRequestNotificationSchema(ma.Schema): class Meta: - fields = ('notificationid', 'requestid', 'idnumber','notification', 'notificationtypelabel','created_at','createdby','updated_at','updatedby','notificationusers') \ No newline at end of file + fields = ('notificationid', 'requestid', 'idnumber','notification', 'notificationtypeid', 'notificationtypelabel','created_at','createdby','updated_at','updatedby','notificationusers') \ No newline at end of file diff --git a/request-management-api/request_api/models/FOIRequestNotificationUsers.py b/request-management-api/request_api/models/FOIRequestNotificationUsers.py index ec5ef8f46..45838d950 100644 --- a/request-management-api/request_api/models/FOIRequestNotificationUsers.py +++ b/request-management-api/request_api/models/FOIRequestNotificationUsers.py @@ -49,8 +49,8 @@ class FOIRequestNotificationUser(db.Model): createdby = db.Column(db.String(120), unique=False, nullable=True) updated_at = db.Column(db.DateTime, nullable=True) updatedby = db.Column(db.String(120), unique=False, nullable=True) - notificationusertypelabel = db.Column(db.String(100),nullable=False) + notificationusertypeid = db.Column(db.Integer,nullable=False) @classmethod @@ -333,4 +333,4 @@ def findfield(cls, x): class FOIRequestNotificationUserSchema(ma.Schema): class Meta: - fields = ('notificationid', 'userid','notificationusertypelabel','created_at','createdby','updated_at','updatedby') \ No newline at end of file + fields = ('notificationid', 'userid','notificationusertypeid', 'notificationusertypelabel','created_at','createdby','updated_at','updatedby') \ No newline at end of file diff --git a/request-management-api/request_api/models/FOIRequestNotifications.py b/request-management-api/request_api/models/FOIRequestNotifications.py index 3ee391f39..c48483388 100644 --- a/request-management-api/request_api/models/FOIRequestNotifications.py +++ b/request-management-api/request_api/models/FOIRequestNotifications.py @@ -31,7 +31,7 @@ class FOIRequestNotification(db.Model): createdby = db.Column(db.String(120), unique=False, nullable=True) 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.String(50), nullable=False) notificationusers = db.relationship('FOIRequestNotificationUser', backref='FOIRequestNotifications', lazy='dynamic') @@ -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, - notificationtypes_cache.replyusercomments.notificationtypelabel, - notificationtypes_cache.taggedusercomments.notificationtypelabel, + notificationtypelabel = [notificationtypes_cache['newusercomments']['notificationtypelabel'], + notificationtypes_cache['replyusercomments']['notificationtypelabel'], + notificationtypes_cache['taggedusercomments']['notificationtypelabel'], ] # 3,9,10 - print(notificationtypelabel) + 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) diff --git a/request-management-api/request_api/models/NotificationUserTypes.py b/request-management-api/request_api/models/NotificationUserTypes.py index 49cadfaaa..2b4e46e16 100644 --- a/request-management-api/request_api/models/NotificationUserTypes.py +++ b/request-management-api/request_api/models/NotificationUserTypes.py @@ -3,6 +3,10 @@ from sqlalchemy.orm import relationship,backref from datetime import datetime from sqlalchemy import text +import json +f = open('common/notificationusertypes.json', encoding="utf8") +notificationusertypes_cache = json.load(f) + class NotificationUserType(db.Model): __tablename__ = 'NotificationUserTypes' @@ -22,8 +26,11 @@ def getnotificationusertypes(cls): # create a class method that returns the notification type id @classmethod def getnotificationusertypesid(cls, notificationusertype): + for usertype in notificationusertypes_cache: + if (notificationusertypes_cache[usertype]['name'] == notificationusertype) or (notificationusertypes_cache[usertype]['notificationusertypelabel'] == notificationusertype): + notificationusertypelabel = notificationusertypes_cache[usertype]['notificationusertypelabel'] type_schema = NotificationUserTypeSchema(many=False) - query = db.session.query(NotificationUserType).filter_by(name=notificationusertype, isactive=True).first() + query = db.session.query(NotificationUserType).filter_by(notificationusertypelabel=notificationusertypelabel, isactive=True).first() return type_schema.dump(query) if query is not None else None diff --git a/request-management-api/request_api/services/notifications/notificationconfig.py b/request-management-api/request_api/services/notifications/notificationconfig.py index 744ab450c..2b4b1ee2e 100644 --- a/request-management-api/request_api/services/notifications/notificationconfig.py +++ b/request-management-api/request_api/services/notifications/notificationconfig.py @@ -11,13 +11,19 @@ class notificationconfig: """ - def getnotificationtypeid(self, notificationtype): + def getnotificationtypelabel(self, notificationtype): id = NotificationType().getnotificationtypeid(notificationtype) if id is not None: return id['notificationtypelabel'] return 0 + + def getnotificationtypeid(self, notificationtype): + id = NotificationType().getnotificationtypeid(notificationtype) + if id is not None: + return id['notificationtypeid'] + return 0 - def getnotificationusertypeid(self, notificationusertype): + def getnotificationusertypelabel(self, notificationusertype): print(notificationusertype) id = NotificationUserType().getnotificationusertypesid(notificationusertype) print(id) @@ -25,6 +31,14 @@ def getnotificationusertypeid(self, notificationusertype): return id['notificationusertypelabel'] return 0 + def getnotificationusertypeid(self, notificationusertype): + print(notificationusertype) + id = NotificationUserType().getnotificationusertypesid(notificationusertype) + print(id) + if id is not None: + return id['notificationusertypeid'] + return 0 + 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/request-management-api/request_api/services/notifications/notificationuser.py b/request-management-api/request_api/services/notifications/notificationuser.py index b7c234ac8..ddfb0cbf3 100644 --- a/request-management-api/request_api/services/notifications/notificationuser.py +++ b/request-management-api/request_api/services/notifications/notificationuser.py @@ -9,7 +9,7 @@ from request_api.services.external.keycloakadminservice import KeycloakAdminService class notificationuser: - """ Notfication user service + """ notification user service """ @@ -55,19 +55,19 @@ def __istaggeduser(self, notificationuser, foicomment, notificationtype): def __getwatchers(self, notificationtype, foirequest, requesttype, requestjson=None): notificationusers = [] if notificationtype == "Watcher": - notificationusers.append({"userid": requestjson['watchedby'], "usertype":notificationconfig().getnotificationusertypeid("Watcher")}) + notificationusers.append({"userid": requestjson['watchedby'], "usertype":notificationconfig().getnotificationusertypelabel("Watcher")}) else: if requesttype == "ministryrequest": watchers = watcherservice().getallministryrequestwatchers(foirequest["foiministryrequestid"], self.__isministryonly(notificationtype)) else: watchers = watcherservice().getrawrequestwatchers(foirequest['requestid']) for watcher in watchers: - notificationusers.append({"userid":watcher["watchedby"], "usertype":notificationconfig().getnotificationusertypeid("Watcher")}) + notificationusers.append({"userid":watcher["watchedby"], "usertype":notificationconfig().getnotificationusertypelabel("Watcher")}) return notificationusers def __getassignees(self, foirequest, requesttype, notificationtype, requestjson=None): notificationusers = [] - notificationtypelabel = notificationconfig().getnotificationusertypeid("Assignee") + notificationtypelabel = notificationconfig().getnotificationusertypelabel("Assignee") if notificationtype == 'User Assignment Removal': notificationusers.append({"userid": requestjson['userid'], "usertype":notificationtypelabel}) else: @@ -102,7 +102,7 @@ def __getcommentusertype(self, userid, requestusers): for requestuser in requestusers: if requestuser["userid"] == userid: return requestuser["usertype"] - return notificationconfig().getnotificationusertypeid("comment user") + return notificationconfig().getnotificationusertypelabel("comment user") def __getrelatedusers(self, comment, requesttype): if requesttype == "ministryrequest": @@ -118,12 +118,12 @@ def __gettaggedusers(self, comment): def __preparetaggeduser(self, data): taggedusers = [] for entry in data: - taggedusers.append({"userid":entry["username"], "usertype":notificationconfig().getnotificationusertypeid("comment tagged user")}) + taggedusers.append({"userid":entry["username"], "usertype":notificationconfig().getnotificationusertypelabel("comment tagged user")}) return taggedusers def __getgroupmembers(self,groupid): notificationusers = [] - notificationtypelabel = notificationconfig().getnotificationusertypeid("Group Members") + notificationtypelabel = notificationconfig().getnotificationtypelabel("Group Members") usergroupfromkeycloak= KeycloakAdminService().getmembersbygroupname(groupid) if usergroupfromkeycloak is not None and len(usergroupfromkeycloak) > 0: for user in usergroupfromkeycloak[0].get("members"): diff --git a/request-management-api/request_api/services/notificationservice.py b/request-management-api/request_api/services/notificationservice.py index a63e30d5a..4b31c3e5d 100644 --- a/request-management-api/request_api/services/notificationservice.py +++ b/request-management-api/request_api/services/notificationservice.py @@ -274,6 +274,7 @@ def __preparenotification(self, message, requesttype, notificationtype, userid, mutenotification = False notification.notificationtypelabel = notificationconfig().getnotificationtypelabel(notificationtype) + notification.notificationtypeid = notificationconfig().getnotificationtypeid(notificationtype) notification.axisnumber = foirequest["axisrequestid"] notification.version = foirequest["version"] notification.createdby = userid @@ -298,6 +299,7 @@ def __preparenotificationuser(self, requesttype, notificationuser, userid, mute= user = FOIRawRequestNotificationUser() user.isdeleted = False user.notificationusertypelabel = notificationuser["usertype"] + user.notificationusertypeid = notificationconfig().getnotificationusertypeid( notificationuser["usertype"]) user.userid = notificationuser["userid"] user.createdby = userid return user From b9223832dbf65c5432561c28cc35fd1aeccc6f62 Mon Sep 17 00:00:00 2001 From: Shivakumar Date: Tue, 12 Dec 2023 13:28:59 -0800 Subject: [PATCH 21/22] Fix merge conflicts --- .../services/notifications/notificationconfig.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/request-management-api/request_api/services/notifications/notificationconfig.py b/request-management-api/request_api/services/notifications/notificationconfig.py index 2b4b1ee2e..da099251d 100644 --- a/request-management-api/request_api/services/notifications/notificationconfig.py +++ b/request-management-api/request_api/services/notifications/notificationconfig.py @@ -24,17 +24,13 @@ def getnotificationtypeid(self, notificationtype): return 0 def getnotificationusertypelabel(self, notificationusertype): - print(notificationusertype) id = NotificationUserType().getnotificationusertypesid(notificationusertype) - print(id) if id is not None: return id['notificationusertypelabel'] return 0 def getnotificationusertypeid(self, notificationusertype): - print(notificationusertype) id = NotificationUserType().getnotificationusertypesid(notificationusertype) - print(id) if id is not None: return id['notificationusertypeid'] return 0 @@ -46,11 +42,7 @@ def getnotificationdays(self): return str(14) def getmutenotifications(self): -<<<<<<< HEAD if 'MUTE_NOTIFICATION' in os.environ and os.getenv('MUTE_NOTIFICATION') != '': -======= - if 'MUTE_NOTIFICATION' in os.environ: ->>>>>>> 21ce0b5a5 (mute notifications for mcf #4548) return json.loads(os.getenv('MUTE_NOTIFICATION')) else: return {} \ No newline at end of file From 12cfdab94fec17f8dec376a2e0ab195199509342 Mon Sep 17 00:00:00 2001 From: divyav-aot Date: Tue, 12 Dec 2023 16:44:23 -0500 Subject: [PATCH 22/22] update to migration script --- .../migrations/versions/d185518c3661_ state_label.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/request-management-api/migrations/versions/d185518c3661_ state_label.py b/request-management-api/migrations/versions/d185518c3661_ state_label.py index 6de636d0a..cc9e43c81 100644 --- a/request-management-api/migrations/versions/d185518c3661_ state_label.py +++ b/request-management-api/migrations/versions/d185518c3661_ state_label.py @@ -129,8 +129,8 @@ def upgrade(): def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.execute('drop view public."v_FOIRawRequests" cascade;') - op.execute('drop view public."v_FOIRequests" cascade;') + op.execute('drop view public."v_FOIRawRequests";') + op.execute('drop view public."v_FOIRequests";') op.execute(""" CREATE OR REPLACE VIEW public."v_FOIRequests" AS SELECT DISTINCT ON (fr.foiministryrequestid) fr.foiministryrequestid,