diff --git a/docker-compose-linux.yml b/docker-compose-linux.yml index 5042af55d..1e7d19852 100644 --- a/docker-compose-linux.yml +++ b/docker-compose-linux.yml @@ -192,6 +192,7 @@ services: - FOI_FFA_URL=${FOI_FFA_URL} - REACT_APP_FOI_RECORD_FORMATS=${FOI_RECORD_FORMATS} - REACT_APP_RECORD_PROCESSING_HRS=${RECORD_PROCESSING_HRS} + - REACT_APP_SESSION_SECURITY_KEY=${REACT_APP_SESSION_SECURITY_KEY} volumes: - ".:/app" - "/app/node_modules" diff --git a/docker-compose.yml b/docker-compose.yml index 7110f214c..b7c2798c4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -229,6 +229,7 @@ services: - REACT_APP_DISABLE_GATHERINGRECORDS_TAB=${DISABLE_GATHERINGRECORDS_TAB} - REACT_APP_RECORD_DOWNLOAD_LIMIT=${RECORD_DOWNLOAD_LIMIT} - REACT_APP_RECORD_DOWNLOAD_SIZE_LIMIT=${RECORD_DOWNLOAD_SIZE_LIMIT} + - REACT_APP_SESSION_SECURITY_KEY=${REACT_APP_SESSION_SECURITY_KEY} volumes: - ".:/app" - "/app/node_modules" diff --git a/forms-flow-web/Dockerfile b/forms-flow-web/Dockerfile index a17c5a25b..2548fca5e 100644 --- a/forms-flow-web/Dockerfile +++ b/forms-flow-web/Dockerfile @@ -37,6 +37,7 @@ ARG REACT_APP_DISABLE_REDACT_WEBLINK ARG REACT_APP_DISABLE_GATHERINGRECORDS_TAB ARG REACT_APP_RECORD_DOWNLOAD_LIMIT ARG REACT_APP_RECORD_DOWNLOAD_SIZE_LIMIT +ARG REACT_APP_SESSION_SECURITY_KEY ENV NODE_ENV ${NODE_ENV} ENV GENERATE_SOURCEMAP ${GENERATE_SOURCEMAP} @@ -66,6 +67,7 @@ ENV REACT_APP_FOI_RECORD_FORMATS ${REACT_APP_FOI_RECORD_FORMATS} ENV REACT_APP_RECORD_PROCESSING_HRS ${REACT_APP_RECORD_PROCESSING_HRS} ENV REACT_APP_DISABLE_REDACT_WEBLINK ${REACT_APP_DISABLE_REDACT_WEBLINK} ENV REACT_APP_DISABLE_GATHERINGRECORDS_TAB ${REACT_APP_DISABLE_GATHERINGRECORDS_TAB} +ENV REACT_APP_SESSION_SECURITY_KEY ${REACT_APP_SESSION_SECURITY_KEY} ENV REACT_APP_SOCKETIO_CONNECT_NONCE ${REACT_APP_SOCKETIO_CONNECT_NONCE} ENV REACT_APP_RECORD_DOWNLOAD_LIMIT ${REACT_APP_RECORD_DOWNLOAD_LIMIT} diff --git a/forms-flow-web/Dockerfile.local b/forms-flow-web/Dockerfile.local index 8ee65d1be..4a7e37583 100644 --- a/forms-flow-web/Dockerfile.local +++ b/forms-flow-web/Dockerfile.local @@ -34,6 +34,7 @@ ARG REACT_APP_DISABLE_REDACT_WEBLINK ARG REACT_APP_DISABLE_GATHERINGRECORDS_TAB ARG REACT_APP_RECORD_DOWNLOAD_LIMIT ARG REACT_APP_RECORD_DOWNLOAD_SIZE_LIMIT +ARG REACT_APP_SESSION_SECURITY_KEY ENV NODE_ENV ${NODE_ENV} ENV GENERATE_SOURCEMAP ${GENERATE_SOURCEMAP} @@ -63,6 +64,7 @@ ENV REACT_APP_DISABLE_REDACT_WEBLINK ${REACT_APP_DISABLE_REDACT_WEBLINK} ENV REACT_APP_DISABLE_GATHERINGRECORDS_TAB ${REACT_APP_DISABLE_GATHERINGRECORDS_TAB} ENV REACT_APP_RECORD_DOWNLOAD_LIMIT ${REACT_APP_RECORD_DOWNLOAD_LIMIT} ENV REACT_APP_RECORD_DOWNLOAD_SIZE_LIMIT ${REACT_APP_RECORD_DOWNLOAD_SIZE_LIMIT} +ENV REACT_APP_SESSION_SECURITY_KEY ${REACT_APP_SESSION_SECURITY_KEY} # add `/app/node_modules/.bin` to $PATH ENV PATH /forms-flow-web/app/node_modules/.bin:$PATH diff --git a/forms-flow-web/docker-compose.yml b/forms-flow-web/docker-compose.yml index d1d17a934..15303ab3d 100644 --- a/forms-flow-web/docker-compose.yml +++ b/forms-flow-web/docker-compose.yml @@ -35,6 +35,7 @@ services: - REACT_APP_FOI_FLOW_REPORTING_URL=${FOI_FLOW_REPORTING_URL} - REACT_APP_AXIS_API_URL=${AXIS_API_URL} - REACT_APP_SOCKETIO_CONNECT_NONCE=${SOCKETIO_CONNECT_NONCE} + - REACT_APP_SESSION_SECURITY_KEY=${REACT_APP_SESSION_SECURITY_KEY} volumes: - ".:/app" - "/app/node_modules" diff --git a/forms-flow-web/src/actions/FOI/foiActionConstants.js b/forms-flow-web/src/actions/FOI/foiActionConstants.js index 863928746..a25278354 100644 --- a/forms-flow-web/src/actions/FOI/foiActionConstants.js +++ b/forms-flow-web/src/actions/FOI/foiActionConstants.js @@ -99,6 +99,9 @@ const FOI_ACTION_CONSTANTS = { FOI_PDF_STITCHED_STATUS_FOR_OIPCREDLINE: "FOI_PDF_STITCHED_STATUS_FOR_OIPCREDLINE", FOI_PDF_STITCHED_RECORD_FOR_OIPCREDLINE: "FOI_PDF_STITCHED_RECORD_FOR_OIPCREDLINE", + FOI_PDF_STITCHED_STATUS_FOR_CONSULTS: "FOI_PDF_STITCHED_STATUS_FOR_CONSULTS", + FOI_PDF_STITCHED_RECORD_FOR_CONSULTS: "FOI_PDF_STITCHED_RECORD_FOR_CONSULTS", + OIPC_OUTCOMES: "OIPC_OUTCOMES", OIPC_STATUSES: "OIPC_STATUSES", OIPC_REVIEWTYPES: "OIPC_REVIEWTYPES", diff --git a/forms-flow-web/src/actions/FOI/foiRequestActions.js b/forms-flow-web/src/actions/FOI/foiRequestActions.js index 6905e67fd..f5a2a1baa 100644 --- a/forms-flow-web/src/actions/FOI/foiRequestActions.js +++ b/forms-flow-web/src/actions/FOI/foiRequestActions.js @@ -165,6 +165,12 @@ export const setFOIPDFStitchedRecordForOipcRedline = (data) => (dispatch) => { payload: data, }); } +export const setFOIPDFStitchedRecordForConsults = (data) => (dispatch) => { + dispatch({ + type: FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_RECORD_FOR_CONSULTS, + payload: data, + }); +} export const setFOIPDFStitchStatusForHarms = (data) => (dispatch) => { dispatch({ type: FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_STATUS_FOR_HARMS, @@ -196,6 +202,12 @@ export const setFOIPDFStitchStatusForOipcRedline = (data) => (dispatch) => { payload: data, }); }; +export const setFOIPDFStitchStatusForConsults = (data) => (dispatch) => { + dispatch({ + type: FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_STATUS_FOR_CONSULTS, + payload: data, + }); +}; export const serviceActionError = (_data) => (dispatch) => { //TODO update to a common file diff --git a/forms-flow-web/src/apiManager/endpoints/index.js b/forms-flow-web/src/apiManager/endpoints/index.js index e0c6bfb08..81a4494db 100644 --- a/forms-flow-web/src/apiManager/endpoints/index.js +++ b/forms-flow-web/src/apiManager/endpoints/index.js @@ -151,6 +151,9 @@ const API = { FOI_DOWNLOAD_RECORDS_FOR_OIPCREDLINE: `${FOI_BASE_API_URL}/api/foirecord//ministryrequest//download/oipcredline`, FOI_PDF_STITCH_STATUS_FOR_OIPCREDLINE: `${FOI_BASE_API_URL}/api/foirecord//ministryrequest//oipcredline/pdfstitchjobstatus`, + FOI_DOWNLOAD_RECORDS_FOR_CONSULTPACKAGE: `${FOI_BASE_API_URL}/api/foirecord//ministryrequest//download/consultpackage`, + FOI_PDF_STITCH_STATUS_FOR_CONSULTPACKAGE: `${FOI_BASE_API_URL}/api/foirecord//ministryrequest//consultpackage/pdfstitchjobstatus`, + FOI_GET_OIPC_OUTCOMES: `${FOI_BASE_API_URL}/api/foiflow/oipc/outcomes`, FOI_GET_OIPC_STATUSES: `${FOI_BASE_API_URL}/api/foiflow/oipc/statuses`, FOI_GET_OIPC_REVIEWTYPES: `${FOI_BASE_API_URL}/api/foiflow/oipc/reviewtypes`, diff --git a/forms-flow-web/src/apiManager/services/FOI/foiMasterDataServices.js b/forms-flow-web/src/apiManager/services/FOI/foiMasterDataServices.js index 7d186c2a8..d57398315 100644 --- a/forms-flow-web/src/apiManager/services/FOI/foiMasterDataServices.js +++ b/forms-flow-web/src/apiManager/services/FOI/foiMasterDataServices.js @@ -698,7 +698,7 @@ import { .then((res) => { if (res.data) { const foiCommentTypes = res.data; - let data = foiCommentTypes.map((type) => { + let data = foiCommentTypes?.map((type) => { return { ...type }; }); dispatch(setFOICommentTypes(data)); diff --git a/forms-flow-web/src/apiManager/services/FOI/foiRecordServices.js b/forms-flow-web/src/apiManager/services/FOI/foiRecordServices.js index bf84ad079..fe861e967 100644 --- a/forms-flow-web/src/apiManager/services/FOI/foiRecordServices.js +++ b/forms-flow-web/src/apiManager/services/FOI/foiRecordServices.js @@ -21,6 +21,8 @@ import { setFOIPDFStitchStatusForOipcRedlineReview, setFOIPDFStitchStatusForOipcRedline, setFOIPDFStitchedRecordForOipcRedline, + setFOIPDFStitchStatusForConsults, + setFOIPDFStitchedRecordForConsults, } from "../../../actions/FOI/foiRequestActions"; import { fnDone } from "./foiServicesUtil"; import UserService from "../../../services/UserService"; @@ -637,6 +639,74 @@ export const fetchPDFStitchedRecordForOIPCRedlineReview = ( }; } +export const fetchPDFStitchStatusForConsults = ( + requestId, + ministryId, + ...rest +) => { + if (!ministryId) { + return () => {}; + } + const done = fnDone(rest); + let apiUrl = replaceUrl( + replaceUrl( + API.FOI_PDF_STITCH_STATUS_FOR_CONSULTPACKAGE, + "", + ministryId + ), + "", + requestId + ); + return (dispatch) => { + httpGETRequest(apiUrl, {}, UserService.getToken()) + .then((res) => { + if (res.data) { + dispatch(setFOIPDFStitchStatusForConsults(res.data)); + done(null, res.data); + } + }) + .catch((error) => { + console.log("Error in fetching pdfstitch job status", error); + dispatch(serviceActionError(error)); + done(error); + }); + }; +} + +export const fetchPDFStitchedRecordForConsults = ( + requestId, + ministryId, + ...rest +) => { + if (!ministryId) { + return () => {}; + } + const done = fnDone(rest); + let apiUrl = replaceUrl( + replaceUrl( + API.FOI_DOWNLOAD_RECORDS_FOR_CONSULTPACKAGE, + "", + ministryId + ), + "", + requestId + ); + return (dispatch) => { + httpGETRequest(apiUrl, {}, UserService.getToken()) + .then((res) => { + if (res.data) { + dispatch(setFOIPDFStitchedRecordForConsults(res.data)); + done(null, res.data); + } + }) + .catch((error) => { + console.log("Error in fetching pdfstitch job status", error); + dispatch(serviceActionError(error)); + done(error); + }); + }; +} + export const updateUserLockedRecords = (data, requestId, ministryId, ...rest) => { const done = fnDone(rest); let apiUrl= replaceUrl(replaceUrl( diff --git a/forms-flow-web/src/components/FOI/Dashboard/Ministry/Queue.js b/forms-flow-web/src/components/FOI/Dashboard/Ministry/Queue.js index a8b92a7ac..277e5168f 100644 --- a/forms-flow-web/src/components/FOI/Dashboard/Ministry/Queue.js +++ b/forms-flow-web/src/components/FOI/Dashboard/Ministry/Queue.js @@ -90,7 +90,7 @@ const Queue = ({ userDetail, tableInfo }) => { function getRecordsDue(params) { let receivedDateString = params.row.cfrduedate; const currentStatus = params.row.currentState; - if (currentStatus.toLowerCase() === StateEnum.onhold.name.toLowerCase()) { + if (currentStatus.toLowerCase() === StateEnum.onhold.name.toLowerCase() || currentStatus.toLowerCase() === StateEnum.onholdother.name.toLowerCase()) { return "N/A"; } else if(!receivedDateString) { return ""; @@ -102,7 +102,7 @@ const Queue = ({ userDetail, tableInfo }) => { function getLDD(params) { let receivedDateString = params.row.duedate; const currentStatus = params.row.currentState; - if (currentStatus.toLowerCase() === StateEnum.onhold.name.toLowerCase()) { + if (currentStatus.toLowerCase() === StateEnum.onhold.name.toLowerCase() || currentStatus.toLowerCase() === StateEnum.onholdother.name.toLowerCase()) { return "N/A"; } else if(!receivedDateString) { return ""; diff --git a/forms-flow-web/src/components/FOI/Dashboard/utils.js b/forms-flow-web/src/components/FOI/Dashboard/utils.js index 086411d30..827e11488 100644 --- a/forms-flow-web/src/components/FOI/Dashboard/utils.js +++ b/forms-flow-web/src/components/FOI/Dashboard/utils.js @@ -133,7 +133,7 @@ export const onBehalfFullName = (params) => { export const getRecordsDue = (params) => { let receivedDateString = params.row.cfrduedate; const currentStatus = params.row.currentState; - if (currentStatus.toLowerCase() === StateEnum.onhold.name.toLowerCase()) { + if (currentStatus.toLowerCase() === StateEnum.onhold.name.toLowerCase() || currentStatus.toLowerCase() === StateEnum.onholdother.name.toLowerCase()) { return "N/A"; } else if(!receivedDateString) { return ""; @@ -145,7 +145,7 @@ export const getRecordsDue = (params) => { export const getLDD = (params) => { let receivedDateString = params.row.duedate; const currentStatus = params.row.currentState; - if (currentStatus.toLowerCase() === StateEnum.onhold.name.toLowerCase()) { + if (currentStatus.toLowerCase() === StateEnum.onhold.name.toLowerCase()||currentStatus.toLowerCase() === StateEnum.onholdother.name.toLowerCase()) { return "N/A"; } else if(!receivedDateString) { return ""; @@ -158,7 +158,7 @@ export const getDaysLeft = (params) => { const receivedDateString = params.row.duedate; if ( - [StateEnum.onhold.name.toLowerCase(), StateEnum.closed.name.toLowerCase()].includes(params.row.currentState.toLowerCase()) + [StateEnum.onhold.name.toLowerCase(), StateEnum.closed.name.toLowerCase(), StateEnum.onholdother.name.toLowerCase()].includes(params.row.currentState.toLowerCase()) ) { return "N/A"; } else if(!receivedDateString) { 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 bbef03d0e..e3650b0bb 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/BottomButtonGroup/index.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/BottomButtonGroup/index.js @@ -369,12 +369,13 @@ const BottomButtonGroup = React.memo( case StateEnum.peerreview.name: case StateEnum.section5pending.name: case StateEnum.appfeeowing.name: + case StateEnum.onholdother.name: case StateEnum.recordsreadyforreview.name: const status = Object.values(StateEnum).find( (statusValue) => statusValue.name === currentSelectedStatus ); saveRequestObject.requeststatuslabel = status.label; - if (currentSelectedStatus === StateEnum.onhold.name && !saveRequestObject.paymentExpiryDate) { + if ((currentSelectedStatus === StateEnum.onhold.name || currentSelectedStatus === StateEnum.onholdother.name) && !saveRequestObject.paymentExpiryDate) { saveRequestObject.paymentExpiryDate = dueDateCalculation(new Date(), PAYMENT_EXPIRY_DAYS); } break; diff --git a/forms-flow-web/src/components/FOI/FOIRequest/ExtensionDetails/ExtensionDetailsBox.js b/forms-flow-web/src/components/FOI/FOIRequest/ExtensionDetails/ExtensionDetailsBox.js index 0e32914db..e512144e7 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/ExtensionDetails/ExtensionDetailsBox.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/ExtensionDetails/ExtensionDetailsBox.js @@ -67,7 +67,7 @@ const ExtensionDetailsBox = React.memo(() => { setExtensionId(null); }} disabled={pendingExtensionExists || requestState?.toLowerCase() === StateEnum.onhold.name.toLowerCase() || - requestState?.toLowerCase() === StateEnum.closed.name.toLowerCase()} + requestState?.toLowerCase() === StateEnum.onholdother.name.toLowerCase() || requestState?.toLowerCase() === StateEnum.closed.name.toLowerCase()} > New Extension diff --git a/forms-flow-web/src/components/FOI/FOIRequest/ExtensionDetails/ExtensionsTable.js b/forms-flow-web/src/components/FOI/FOIRequest/ExtensionDetails/ExtensionsTable.js index 08d1293e7..09f914cf4 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/ExtensionDetails/ExtensionsTable.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/ExtensionDetails/ExtensionsTable.js @@ -168,7 +168,7 @@ const ExtensionsTable = ({ showActions = true }) => { disabled={ (index > 0 && extension.extensionstatus !== extensionStatusId.pending) || requestState?.toLowerCase() === StateEnum.onhold.name.toLowerCase() || - requestState?.toLowerCase() === StateEnum.closed.name.toLowerCase() + requestState?.toLowerCase() === StateEnum.onholdother.name.toLowerCase() || requestState?.toLowerCase() === StateEnum.closed.name.toLowerCase() } > diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index cd270d116..e548f2e13 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -55,6 +55,7 @@ import { fetchPDFStitchStatusForResponsePackage, fetchPDFStitchedStatusForOIPCRedlineReview, fetchPDFStitchedStatusForOIPCRedline, + fetchPDFStitchStatusForConsults, } from "../../../apiManager/services/FOI/foiRecordServices"; import { makeStyles } from "@material-ui/core/styles"; import FOI_COMPONENT_CONSTANTS from "../../../constants/FOI/foiComponentConstants"; @@ -325,6 +326,7 @@ const FOIRequest = React.memo(({ userDetail, openApplicantProfileModal }) => { dispatch(fetchPDFStitchStatusForResponsePackage(requestId, ministryId)); dispatch(fetchPDFStitchedStatusForOIPCRedline(requestId, ministryId)); dispatch(fetchPDFStitchedStatusForOIPCRedlineReview(requestId, ministryId)); + dispatch(fetchPDFStitchStatusForConsults(requestId, ministryId)); fetchCFRForm(ministryId, dispatch); dispatch(fetchApplicantCorrespondence(requestId, ministryId)); dispatch(fetchApplicantCorrespondenceTemplates()); @@ -361,6 +363,7 @@ const FOIRequest = React.memo(({ userDetail, openApplicantProfileModal }) => { currentState === StateEnum.peerreview.name || currentState === StateEnum.signoff.name || currentState === StateEnum.response.name || + currentState === StateEnum.onholdother.name || currentState === StateEnum.closed.name ); } @@ -881,7 +884,6 @@ const FOIRequest = React.memo(({ userDetail, openApplicantProfileModal }) => { const handleSaveRequest = (_state, _unSaved, id) => { setHeader(_state); - if (!_unSaved) { setUnSavedRequest(_unSaved); dispatch(fetchFOIRequestDetailsWrapper(id || requestId, ministryId)); @@ -1030,7 +1032,6 @@ const FOIRequest = React.memo(({ userDetail, openApplicantProfileModal }) => { (state) => state.foiRequests.showEventQueue ); - //console.log("IAO:::", iaoassignedToList) const showRecordsTab = () => { return ( requestState !== StateEnum.intakeinprogress.name && diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js index 1e57d56e2..6437965c4 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js @@ -225,6 +225,7 @@ const FOIRequestHeader = React.memo( status.toLowerCase() === StateEnum.onhold.name.toLowerCase() || status.toLowerCase() === StateEnum.response.name.toLowerCase() || status.toLowerCase() === StateEnum.recordsreadyforreview.name.toLowerCase() || + status.toLowerCase() === StateEnum.onholdother.name.toLowerCase() || (ministryId && status.toLowerCase() === StateEnum.peerreview.name.toLowerCase()); const getMinistryAssignedTo = () => { 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 a89a289bf..9459d9a31 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReview.js @@ -263,6 +263,7 @@ const MinistryReview = React.memo(({ userDetail }) => { currentState === StateEnum.peerreview.name || currentState === StateEnum.signoff.name || currentState === StateEnum.response.name || + currentState === StateEnum.onholdother.name || currentState === StateEnum.closed.name ); } @@ -328,6 +329,7 @@ const MinistryReview = React.memo(({ userDetail }) => { const [CFRUnsaved, setCFRUnsaved] = React.useState(false); const hideBottomText = [ StateEnum.onhold.name.toLowerCase(), + StateEnum.onholdother.name.toLowerCase(), StateEnum.closed.name.toLowerCase(), ]; @@ -489,6 +491,9 @@ const MinistryReview = React.memo(({ userDetail }) => { break; case StateEnum.recordsreadyforreview.name: foitabheaderBG = "foitabheadercollection foitabheaderRecordsReadyForReviewBG"; + break; + case StateEnum.onholdother.name: + foitabheaderBG = "foitabheadercollection foitabheaderOnHoldOtherBG"; break; default: foitabheaderBG = "foitabheadercollection foitabheaderdefaultBG"; diff --git a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReviewTabbedContainer.scss b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReviewTabbedContainer.scss index fd1a57bdc..617a97784 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReviewTabbedContainer.scss +++ b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/MinistryReviewTabbedContainer.scss @@ -214,7 +214,9 @@ .foitabheaderPeerreviewBG{ background-color: #096DD1; } - + .foitabheaderOnHoldOtherBG{ + background-color: #595959; + } .foileftpanelheader { padding-left: 12%; diff --git a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/RequestDetails.js b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/RequestDetails.js index 2e4c233a4..ec9a9472a 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/RequestDetails.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/MinistryReview/RequestDetails.js @@ -57,8 +57,9 @@ const RequestDetails = React.memo((requestDetails) => { Records Due Date - {_requestDetails?.currentState?.toLowerCase() !== - StateEnum.onhold.name.toLowerCase() + {(_requestDetails?.currentState?.toLowerCase() !== + StateEnum.onhold.name.toLowerCase() && _requestDetails?.currentState?.toLowerCase() !== + StateEnum.onholdother.name.toLowerCase()) ? formatDate( _requestDetails.cfrDueDate, "MMM dd yyyy" @@ -71,8 +72,9 @@ const RequestDetails = React.memo((requestDetails) => { Legislated Due Date - {_requestDetails?.currentState?.toLowerCase() !== - StateEnum.onhold.name.toLowerCase() + {(_requestDetails?.currentState?.toLowerCase() !== + StateEnum.onhold.name.toLowerCase() && _requestDetails?.currentState?.toLowerCase() !== + StateEnum.onholdother.name.toLowerCase()) ? formatDate( _requestDetails.dueDate, "MMM dd yyyy" diff --git a/forms-flow-web/src/components/FOI/FOIRequest/RequestDetails.js b/forms-flow-web/src/components/FOI/FOIRequest/RequestDetails.js index 43e4b4ae1..64ac1aa60 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/RequestDetails.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/RequestDetails.js @@ -265,8 +265,8 @@ const RequestDetails = React.memo( { return "foitabheadercollection foitabheaderAppFeeOwingBG"; case StateEnum.recordsreadyforreview.name: return "foitabheadercollection foitabheaderRecordsReadyForReviewBG"; - + case StateEnum.onholdother.name: + return "foitabheadercollection foitabheaderOnholdOtherBG"; default: return "foitabheadercollection foitabheaderdefaultBG"; } @@ -371,7 +373,6 @@ export const checkValidationError = ( */ //Below function will handle beforeunload event export const alertUser = (e) => { - console.log("alertUser:",e) e.preventDefault(); e.returnValue = ""; }; @@ -399,8 +400,6 @@ export const shouldDisableFieldForMinistryRequests = (requestStatus) => { }; export const handleBeforeUnload = (e) => { - console.log("handleBeforeUnload:",e) - alertUser(e); }; diff --git a/forms-flow-web/src/components/FOI/customComponents/Attachments/AttachmentModal.js b/forms-flow-web/src/components/FOI/customComponents/Attachments/AttachmentModal.js index 73e2dbbae..907436dfb 100644 --- a/forms-flow-web/src/components/FOI/customComponents/Attachments/AttachmentModal.js +++ b/forms-flow-web/src/components/FOI/customComponents/Attachments/AttachmentModal.js @@ -670,7 +670,7 @@ export default function AttachmentModal({ MCFPopularSections - 1 )} otherTagList={MCFSections?.sections?.slice( - MCFPopularSections + MCFPopularSections - 1 )} handleTagChange={handleTagChange} tagValue={tagValue} @@ -712,7 +712,7 @@ export default function AttachmentModal({ MSDPopularSections - 1 )} otherTagList={MSDSections?.divisions[0]?.sections?.slice( - MSDPopularSections + MSDPopularSections - 1 )} handleTagChange={handleTagChange} tagValue={tagValue} diff --git a/forms-flow-web/src/components/FOI/customComponents/CFRForm/index.tsx b/forms-flow-web/src/components/FOI/customComponents/CFRForm/index.tsx index e916cf549..266364600 100644 --- a/forms-flow-web/src/components/FOI/customComponents/CFRForm/index.tsx +++ b/forms-flow-web/src/components/FOI/customComponents/CFRForm/index.tsx @@ -379,14 +379,14 @@ export const CFRForm = ({ if(requestState === StateEnum.peerreview.name){ return true; } - if (formHistory.length > 0 && [StateEnum.feeassessed.name, StateEnum.onhold.name, StateEnum.callforrecords.name].includes(requestState)) { + if (formHistory.length > 0 && [StateEnum.feeassessed.name, StateEnum.onhold.name, StateEnum.callforrecords.name, StateEnum.onholdother.name].includes(requestState)) { if (isMinistry) { return ['review', 'approved'].includes(initialFormData.formStatus) || isNewCFRForm; } else { return initialFormData.formStatus !== 'review'; } } - if (formData.balanceRemaining > 0 && [StateEnum.feeassessed.name, StateEnum.onhold.name].includes(requestState)) { + if (formData.balanceRemaining > 0 && [StateEnum.feeassessed.name, StateEnum.onhold.name, StateEnum.onholdother.name].includes(requestState)) { if (isMinistry) { return !['clarification', 'init'].includes(initialFormData.formStatus); } else { @@ -523,7 +523,8 @@ export const CFRForm = ({ const disableNewCfrFormBtn = () => { return(formData?.formStatus !== 'approved' || requestState === StateEnum.peerreview.name || (requestState !== StateEnum.callforrecords.name && - requestState !== StateEnum.feeassessed.name && requestState !== StateEnum.onhold.name) || (requestState === StateEnum.onhold.name && formData?.actualTotalDue > 0)); + requestState !== StateEnum.feeassessed.name && requestState !== StateEnum.onhold.name) || (requestState === StateEnum.onhold.name && formData?.actualTotalDue > 0) || + (requestState === StateEnum.onholdother.name && formData?.actualTotalDue > 0)); } const disableAmountPaid = () => { @@ -544,7 +545,7 @@ export const CFRForm = ({ } const isFeeWaiverDisabled = () => { - if(isMinistry || requestState === StateEnum.peerreview.name || (!isMinistry && (requestState !== StateEnum.onhold.name || formData?.formStatus !== 'approved'))) + if(isMinistry || requestState === StateEnum.peerreview.name || (!isMinistry && (requestState !== StateEnum.onhold.name || requestState !== StateEnum.onholdother.name || formData?.formStatus !== 'approved'))) return true; else return false; diff --git a/forms-flow-web/src/components/FOI/customComponents/Comments/AddCommentField.js b/forms-flow-web/src/components/FOI/customComponents/Comments/AddCommentField.js index a7b4f8294..39bcb7c09 100644 --- a/forms-flow-web/src/components/FOI/customComponents/Comments/AddCommentField.js +++ b/forms-flow-web/src/components/FOI/customComponents/Comments/AddCommentField.js @@ -86,11 +86,8 @@ const AddCommentField = ({ cancellor, parentId, add, fullnameList , restrictedRe const _handleChange = (_editorState) => { const currentContent = _editorState.getCurrentContent(); const currentContentLength = currentContent.getPlainText('').length; - //console.log("**currentContentLength:", currentContentLength) const selectedTextLength = _getLengthOfSelectedText(); - //console.log("**selectedTextLength:", selectedTextLength) let _textLength = maxcharacterlimit - (currentContentLength - selectedTextLength) - //console.log("**_textLength:", _textLength) if(_textLength > 0) {setTextLength(maxcharacterlimit - (currentContentLength - selectedTextLength))} @@ -143,16 +140,12 @@ const AddCommentField = ({ cancellor, parentId, add, fullnameList , restrictedRe const currentContent = editorState.getCurrentContent(); const currentContentLength = currentContent.getPlainText('').length; const selectedTextLength = _getLengthOfSelectedText(); - // console.log("**1currentContentLength:", currentContentLength) - // console.log("**1selectedTextLength:", selectedTextLength) - if ((e === 'backspace' || e === 'delete') && currentContentLength - 1 >= 0) { setTextLength((maxcharacterlimit) - (currentContentLength - 1)) } if ((e === 'backspace' || e === 'delete') && selectedTextLength > 0) { setTextLength(maxcharacterlimit - (currentContentLength - selectedTextLength)) } - //console.log("**1_textLength:", textlength) setuftext(currentContent.getPlainText('')) //For enabling keyboard shortcuts const newState = RichUtils.handleKeyCommand(editorState, e); @@ -166,8 +159,6 @@ const AddCommentField = ({ cancellor, parentId, add, fullnameList , restrictedRe const currentContent = editorState.getCurrentContent(); const currentContentLength = currentContent.getPlainText('').length; const selectedTextLength = _getLengthOfSelectedText(); - // console.log("**2currentContentLength:", currentContentLength) - // console.log("**2selectedTextLength:", selectedTextLength) if (currentContentLength - selectedTextLength > maxcharacterlimit - 1) { return 'handled'; } @@ -175,15 +166,12 @@ const AddCommentField = ({ cancellor, parentId, add, fullnameList , restrictedRe setTextLength((maxcharacterlimit - 1) - (currentContentLength - selectedTextLength)) } setuftext(currentContent.getPlainText('')) - //console.log("**2textLength:", textlength) } const _handlePastedText = (pastedText) => { const currentContent = editorState.getCurrentContent(); const currentContentLength = currentContent.getPlainText('').length; const selectedTextLength = _getLengthOfSelectedText(); - // console.log("**3currentContentLength:", currentContentLength) - // console.log("**3selectedTextLength:", selectedTextLength) if (currentContentLength + pastedText.length - selectedTextLength > maxcharacterlimit) { return 'handled'; } @@ -191,8 +179,6 @@ const AddCommentField = ({ cancellor, parentId, add, fullnameList , restrictedRe setTextLength((maxcharacterlimit) - (currentContentLength + pastedText.length - selectedTextLength)) } setuftext(currentContent.getPlainText('')) - //console.log("**3textLength:", textlength) - } diff --git a/forms-flow-web/src/components/FOI/customComponents/Comments/CommentStructure.js b/forms-flow-web/src/components/FOI/customComponents/Comments/CommentStructure.js index e84a5f4e6..4db8750e7 100644 --- a/forms-flow-web/src/components/FOI/customComponents/Comments/CommentStructure.js +++ b/forms-flow-web/src/components/FOI/customComponents/Comments/CommentStructure.js @@ -70,7 +70,7 @@ const CommentStructure = ({ i, reply, parentId, totalcommentCount, currentIndex, const getHtmlfromRawContent = () => { let markup = null - if (i.commentTypeId !== 2 && i.commentTypeId !== 3) { + if (i.commentTypeId != null && i.commentTypeId !== 2 && i.commentTypeId !== 3) { const rawContentFromStore = convertFromRaw(JSON.parse(i.text)) let initialEditorState = EditorState.createWithContent(rawContentFromStore); @@ -267,7 +267,7 @@ const CommentStructure = ({ i, reply, parentId, totalcommentCount, currentIndex,
{fullName}
|
{i.date}
- {(i.commentTypeId !== 2 && i.commentTypeId !== 3 && (parentId == null || parentId == undefined)) && + {(i.commentTypeId != null && i.commentTypeId !== 2 && i.commentTypeId !== 3 && (parentId == null || parentId == undefined)) &&
- {(isEmail || ((i.commentTypeId !== 2 && i.commentTypeId !== 3) && actions.userId === i.userId && actions.user)) && ( + {(isEmail || ((i.commentTypeId != null && i.commentTypeId !== 2 && i.commentTypeId !== 3) && actions.userId === i.userId && actions.user)) && ( <> { - //console.log("setTeamTagList useeffect", bcgovcode) setTeamTagList(bcgovcode) }, [fullnameList]) diff --git a/forms-flow-web/src/components/FOI/customComponents/Comments/Input.js b/forms-flow-web/src/components/FOI/customComponents/Comments/Input.js index d70da3494..df11ed5e9 100644 --- a/forms-flow-web/src/components/FOI/customComponents/Comments/Input.js +++ b/forms-flow-web/src/components/FOI/customComponents/Comments/Input.js @@ -9,11 +9,6 @@ const Input = ({ add, bcgovcode, iaoassignedToList, ministryAssignedToList, setE const [fullnameList, setFullnameList] = useState(getFullnameList()); - - // useEffect(() => { - // console.log("setTeamTagList useeffect") - // setTeamTagList() - // }, []) if (!fullnameList) { if (iaoassignedToList.length > 0) { diff --git a/forms-flow-web/src/components/FOI/customComponents/Comments/InputField.js b/forms-flow-web/src/components/FOI/customComponents/Comments/InputField.js index 4c1d56446..eb681ef13 100644 --- a/forms-flow-web/src/components/FOI/customComponents/Comments/InputField.js +++ b/forms-flow-web/src/components/FOI/customComponents/Comments/InputField.js @@ -73,7 +73,6 @@ const InputField = ({ cancellor, parentId, child, inputvalue, edit, main, add, f } useEffect(() => { - //console.log("isCommentTagListLoading - Use effect") setMentionList(isCommentTagListLoading ? [{name: 'Loading...'}] : isRestricted ? restrictedReqTaglist :suggestionList(filterTagList(editCommentTypeId)).sort(namesort)); setSuggestions(isCommentTagListLoading ? [{name: 'Loading...'}] : isRestricted ? restrictedReqTaglist : mentionList)//suggestionList(filterTagList(editCommentTypeId)).sort(namesort)); }, [isCommentTagListLoading, restrictedReqTaglist]) diff --git a/forms-flow-web/src/components/FOI/customComponents/Comments/commentutils.js b/forms-flow-web/src/components/FOI/customComponents/Comments/commentutils.js index 0b95fb81a..972c0f59e 100644 --- a/forms-flow-web/src/components/FOI/customComponents/Comments/commentutils.js +++ b/forms-flow-web/src/components/FOI/customComponents/Comments/commentutils.js @@ -10,7 +10,6 @@ } const suggestionList = (teamlist) =>{ - //console.log("teamlist:", teamlist) teamlist.forEach(ful => { ful.name = ful.fullname; if(ful.fullname?.indexOf(',')> 0) 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 d3eacd84a..9ddc823c8 100644 --- a/forms-flow-web/src/components/FOI/customComponents/ConfirmationModal/index.js +++ b/forms-flow-web/src/components/FOI/customComponents/ConfirmationModal/index.js @@ -169,7 +169,6 @@ export default function ConfirmationModal({requestId, openModal, handleModal, st else if (saveRequestObject.requeststatuslabel === StateEnum.signoff.label && state.toLowerCase() === StateEnum.review.name.toLowerCase()) fileStatusTransition = StateTransitionCategories.signoffreview.name; - fileInfoList = files.map(file => { return { ministrycode: requestNumber.split("-")[0], @@ -186,7 +185,7 @@ export default function ConfirmationModal({requestId, openModal, handleModal, st const attchmentFileNameList = attachmentsArray?.map(_file => _file.filename); const getDaysRemaining = () => { - if (currentState?.toLowerCase() === StateEnum.closed.name.toLowerCase() && state.toLowerCase() !== StateEnum.closed.name.toLowerCase() && state.toLowerCase() !== StateEnum.onhold.name.toLowerCase()) { + if (currentState?.toLowerCase() === StateEnum.closed.name.toLowerCase() && state.toLowerCase() !== StateEnum.closed.name.toLowerCase() && state.toLowerCase() !== StateEnum.onhold.name.toLowerCase() && state.toLowerCase() !== StateEnum.onholdother.name.toLowerCase()) { return ( {daysRemainingLDD} DAYS REMAINING ); @@ -194,7 +193,9 @@ export default function ConfirmationModal({requestId, openModal, handleModal, st } const addorUpdateConfirmationModal = () => { - if (state.toLowerCase() === StateEnum.closed.name.toLowerCase() && + if(currentState?.toLowerCase() === StateEnum.onholdother.name.toLowerCase()) + return null; + else if (state.toLowerCase() === StateEnum.closed.name.toLowerCase() && currentState?.toLowerCase() !== StateEnum.closed.name.toLowerCase()) { return ( @@ -261,7 +262,7 @@ export default function ConfirmationModal({requestId, openModal, handleModal, st : null } - {(currentState?.toLowerCase() !== StateEnum.closed.name.toLowerCase() && [StateEnum.callforrecords.name.toLowerCase(), StateEnum.consult.name.toLowerCase(), StateEnum.onhold.name.toLowerCase()].includes(state.toLowerCase())) ? + {(currentState?.toLowerCase() !== StateEnum.closed.name.toLowerCase() && [StateEnum.callforrecords.name.toLowerCase(), StateEnum.consult.name.toLowerCase(), StateEnum.onhold.name.toLowerCase(), StateEnum.onholdother.name.toLowerCase()].includes(state.toLowerCase())) ? 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 a3058bcbe..1261d34d0 100644 --- a/forms-flow-web/src/components/FOI/customComponents/ConfirmationModal/util.js +++ b/forms-flow-web/src/components/FOI/customComponents/ConfirmationModal/util.js @@ -46,6 +46,9 @@ import FOI_COMPONENT_CONSTANTS from '../../../../constants/FOI/foiComponentConst _saveRequestObject.reopen = true; return {title: "Re-Open Request", body: <>Are you sure you want to re-open Request # {_requestNumber ? _requestNumber : `U-00${_requestId}`}?
The request will be re-opened to the previous state: {_state} }; } + if ((_currentState?.toLowerCase() === StateEnum.onholdother.name.toLowerCase())){ + return {title: "Taking Request off hold", body: "Are you sure you want to take this request off hold? The legislated due date will be recalculated"}; + } switch(_state.toLowerCase()) { case StateEnum.intakeinprogress.name.toLowerCase(): return {title: "Changing the state", body: "Are you sure you want to change the state to Intake in Progress?"}; @@ -134,6 +137,9 @@ import FOI_COMPONENT_CONSTANTS from '../../../../constants/FOI/foiComponentConst return {title: "Changing the state", body: `Are you sure you want to change Request #${_requestNumber} to ${StateEnum.response.name}?`}; case StateEnum.appfeeowing.name.toLowerCase(): return {title: "Changing the state", body: `Are you sure you want to change Request #${_requestNumber} to ${StateEnum.appfeeowing.name}?`}; + case StateEnum.onholdother.name.toLowerCase(): + return {title: "Change Request to On Hold - other", + body: "Are you sure you want to put this request on hold - Other? This should only be used for reasons other than fees when you need to put a request on hold (eg - Third Party notice, or Intake related reasons)"}; default: return {title: "", body: ""}; } diff --git a/forms-flow-web/src/components/FOI/customComponents/FileUpload/FileUploadForMCFPersonal.js b/forms-flow-web/src/components/FOI/customComponents/FileUpload/FileUploadForMCFPersonal.js index e2684629f..982b85b94 100644 --- a/forms-flow-web/src/components/FOI/customComponents/FileUpload/FileUploadForMCFPersonal.js +++ b/forms-flow-web/src/components/FOI/customComponents/FileUpload/FileUploadForMCFPersonal.js @@ -83,8 +83,8 @@ const FileUploadForMCFPersonal = ({ isMinistryCoordinator?MCFPeople?.people.filter((p)=>{return p.name !== 'PERSON 1'}):MCFPeople?.people.filter((p)=>{return p.name !== 'APPLICANT'}) ); const [allVolumes, setAllVolumes] = useState(MCFVolumes?.volumes); - const [fileTypes, setFileTypes] = useState(MCFFiletypes?.filetypes.slice(0, 6)); - const [otherFileTypes, setOtherFileTypes] = useState(MCFFiletypes?.filetypes.slice(6, MCFFiletypes?.filetypes.length)); + const [fileTypes, setFileTypes] = useState(MCFFiletypes?.filetypes.slice(0, 8)); + const [otherFileTypes, setOtherFileTypes] = useState(MCFFiletypes?.filetypes.slice(8, MCFFiletypes?.filetypes.length)); const [people, setPeople] = useState(allPeople.slice(0, 5)); const [volumes, setVolumes] = useState(allVolumes.slice(0, 5)); const [showAllPeople, setShowAllPeople] = useState(false); @@ -212,13 +212,9 @@ const FileUploadForMCFPersonal = ({ const fileDrop = (e) => { e.preventDefault(); - if(modalFor === "add" && (!isPersonSelected || ((isMinistryCoordinator && tagValue == "")))) { - return - } else { - const newFiles = e.dataTransfer.files; - const totalNoOfFiles = Object.entries(files).length + newFiles.length; - validateFiles(newFiles, totalNoOfFiles); - } + const newFiles = e.dataTransfer.files; + const totalNoOfFiles = Object.entries(files).length + newFiles.length; + validateFiles(newFiles, totalNoOfFiles); } const removeFile = (fileName) => { const _file = files[fileName]; @@ -712,12 +708,11 @@ const FileUploadForMCFPersonal = ({ value="" multiple={multipleFiles} accept={mimeTypes} - disabled={modalFor === "add" && (!isPersonSelected || ((isMinistryCoordinator && tagValue == "")))} />
{(Object.entries(files).length === 0 && !multipleFiles) || multipleFiles ? - : null}
diff --git a/forms-flow-web/src/components/FOI/customComponents/Records/MCFPersonal.js b/forms-flow-web/src/components/FOI/customComponents/Records/MCFPersonal.js index ba12bf232..ef6734a60 100644 --- a/forms-flow-web/src/components/FOI/customComponents/Records/MCFPersonal.js +++ b/forms-flow-web/src/components/FOI/customComponents/Records/MCFPersonal.js @@ -25,7 +25,7 @@ const MCFPersonal = ({ editTagModalOpen, setEditTagModalOpen, setNewDivision, - // tagValue, + comparePersonalAttributes, curPersonalAttributes, setNewPersonalAttributes, updatePersonalAttributes, @@ -74,6 +74,24 @@ const MCFPersonal = ({ const [fileTypeSearchValue, setFileTypeSearchValue] = useState(""); const [additionalFileTypes, setAdditionalFileTypes] = useState([]); const [showAdditionalFileTypes, setShowAdditionalFileTypes] = useState(false); + const [disableSave, setDisableSave] = useState(false); + + const compareDivision = (curDiv, newDiv) => { + return curDiv === newDiv; + } + + useEffect(() => { + setDisableSave( + personalAttributes?.person === undefined + || personalAttributes?.person === "" + || personalAttributes?.filetype === undefined + || personalAttributes?.filetype === "" + || personalAttributes?.trackingid === undefined + || personalAttributes?.trackingid === "" + || (!isMinistryCoordinator && comparePersonalAttributes(personalAttributes, curPersonalAttributes)) + || (isMinistryCoordinator && comparePersonalAttributes(personalAttributes, curPersonalAttributes) && compareDivision(currentEditRecord.attributes.divisions[0].divisionid, divisionModalTagValue)) + ); + },[personalAttributes, divisionModalTagValue]) useEffect(() => { if(currentEditRecord?.attributes?.divisions[0]?.divisionid) { @@ -85,7 +103,7 @@ const MCFPersonal = ({ if(MCFSections?.sections) { if(MCFSections.sections.length > MCFPopularSections-1) { setTagList(MCFSections.sections.slice(0, MCFPopularSections-1)); - setOtherTagList(MCFSections.sections.slice(MCFPopularSections)); + setOtherTagList(MCFSections.sections.slice(MCFPopularSections-1)); } else { setTagList(MCFSections.sections); setOtherTagList([]); @@ -118,8 +136,8 @@ const MCFPersonal = ({ useEffect(() => { if(MCFFiletypes?.filetypes) { if(MCFFiletypes.filetypes?.length > 6) { - setFileTypes(MCFFiletypes.filetypes.slice(0, 6)); - setOtherFileTypes(MCFFiletypes.filetypes.slice(6, MCFFiletypes.filetypes.length)) + setFileTypes(MCFFiletypes.filetypes.slice(0, 8)); + setOtherFileTypes(MCFFiletypes.filetypes.slice(8, MCFFiletypes.filetypes.length)) } else { setFileTypes(MCFFiletypes.filetypes); setOtherFileTypes([]) @@ -622,13 +640,14 @@ const MCFPersonal = ({ diff --git a/forms-flow-web/src/components/FOI/customComponents/Records/index.js b/forms-flow-web/src/components/FOI/customComponents/Records/index.js index e523f7b0e..fe7b6620a 100644 --- a/forms-flow-web/src/components/FOI/customComponents/Records/index.js +++ b/forms-flow-web/src/components/FOI/customComponents/Records/index.js @@ -33,6 +33,7 @@ import { fetchPDFStitchedRecordForOIPCRedline, fetchPDFStitchedRecordForOIPCRedlineReview, checkForRecordsChange, + fetchPDFStitchedRecordForConsults, editPersonalAttributes, updateUserLockedRecords, } from "../../../../apiManager/services/FOI/foiRecordServices"; @@ -252,6 +253,9 @@ export const RecordsLog = ({ let responsePackagePdfStitchStatus = useSelector( (state) => state.foiRequests.foiPDFStitchStatusForResponsePackage ); + let consultPDFStitchedStatus = useSelector( + (state) => state.foiRequests.foiPDFStitchStatusForConsults + ); let pdfStitchedRecord = useSelector( (state) => state.foiRequests.foiPDFStitchedRecordForHarms @@ -268,6 +272,9 @@ export const RecordsLog = ({ let responsePackagePdfStitchedRecord = useSelector( (state) => state.foiRequests.foiPDFStitchedRecordForResponsePackage ); + let consultPDFStitchedRecord = useSelector( + (state) => state.foiRequests.foiPDFStitchedRecordForConsultPackage + ); let isRecordsfetching = useSelector( (state) => state.foiRequests.isRecordsLoading @@ -317,6 +324,12 @@ export const RecordsLog = ({ useEffect(() => { dispatch(getRecordFormats()); + + + //Filter out download consults option from RecordsDownloadList if ministry user + if (isMinistryCoordinator) { + setRecordsDownloadList(recordsDownloadList.filter((record) => record.id !== 6)); + } }, []); const [currentEditRecord, setCurrentEditRecord] = useState(); @@ -487,6 +500,11 @@ export const RecordsLog = ({ useState(false); const [isOIPCRedlineInProgress, setIsOIPCRedlineInProgress] = useState(false); + + const [isConsultDownloadInProgress, setIsConsultDownloadInProgress] = useState(false); + const [isConsultDownloadReady, setIsConsultDownloadReady] = useState(false); + const [isConsultDownloadFailed, setIsConsultDownloadFailed] = useState(false); + const [isAllSelected, setIsAllSelected] = useState(false); useEffect(() => { @@ -569,12 +587,21 @@ export const RecordsLog = ({ setIsOIPCRedlineFailed, fetchPDFStitchedRecordForOIPCRedline ); + // Update Consult Stitch Status + updateStatus( + consultPDFStitchedStatus, + setIsConsultDownloadInProgress, + setIsConsultDownloadReady, + setIsConsultDownloadFailed, + fetchPDFStitchedRecordForConsults + ); }, [ pdfStitchStatus, redlinePdfStitchStatus, responsePackagePdfStitchStatus, oipcRedlinePdfStitchedStatus, oipcRedlineReviewPdfStitchedStatus, + consultPDFStitchedStatus, requestId, ministryId, ]); @@ -593,8 +620,11 @@ export const RecordsLog = ({ if (item.id === 5 && isOIPCRedlineReviewReady) { item.disabled = false; } + if (item.id === 6 && isConsultDownloadReady) { + item.disabled = false; + } }); - }, [isRedlineDownloadReady, isResponsePackageDownloadReady, isOIPCRedlineReady, isOIPCRedlineReviewReady]); + }, [isRedlineDownloadReady, isResponsePackageDownloadReady, isOIPCRedlineReady, isOIPCRedlineReviewReady, isConsultDownloadReady]); const addAttachments = () => { setModalFor("add"); @@ -979,6 +1009,9 @@ export const RecordsLog = ({ } else if (e.target.value === 5 && isOIPCRedlineReviewReady) { const s3filepath = oipcRedlineReviewPdfStitchedRecord?.finalpackagepath; handleDownloadZipFile(s3filepath, e.target.value); + } else if (e.target.value === 6 && isConsultDownloadReady) { + const s3filepath = consultPDFStitchedRecord?.finalpackagepath; + handleDownloadZipFile(s3filepath, e.target.value); } setCurrentDownload(e.target.value); @@ -1161,6 +1194,10 @@ export const RecordsLog = ({ setIsOIPCRedlineReviewInProgress(false); setIsOIPCRedlineReviewReady(false); setIsOIPCRedlineReviewFailed(true); + } else if (itemid === 6) { + setIsConsultDownloadInProgress(false); + setIsConsultDownloadReady(false); + setIsConsultDownloadFailed(true); } }; @@ -1170,7 +1207,8 @@ export const RecordsLog = ({ (itemid === 2 && isRedlineDownloadReady) || (itemid === 3 && isResponsePackageDownloadReady) || (itemid === 4 && isOIPCRedlineReady) || - (itemid === 5 && isOIPCRedlineReviewReady) + (itemid === 5 && isOIPCRedlineReviewReady) || + (itemid === 6 && isConsultDownloadReady) ); }; @@ -1180,7 +1218,8 @@ export const RecordsLog = ({ (itemid === 2 && isRedlineDownloadFailed) || (itemid === 3 && isResponsePackageDownloadFailed) || (itemid === 4 && isOIPCRedlineFailed) || - (itemid === 5 && isOIPCRedlineReviewFailed) + (itemid === 5 && isOIPCRedlineReviewFailed) || + (itemid === 6 && isConsultDownloadFailed) ); }; @@ -1190,7 +1229,8 @@ export const RecordsLog = ({ (itemid === 2 && isRedlineDownloadInProgress) || (itemid === 3 && isResponsePackageDownloadInProgress) || (itemid === 4 && isOIPCRedlineInProgress) || - (itemid === 5 && isOIPCRedlineReviewInProgress) + (itemid === 5 && isOIPCRedlineReviewInProgress) || + (itemid === 6 && isConsultDownloadInProgress) ); }; @@ -1200,7 +1240,8 @@ export const RecordsLog = ({ (itemid === 2 && redlinePdfStitchedRecord?.createdat_datetime) || (itemid === 3 && responsePackagePdfStitchedRecord?.createdat_datetime) || (itemid === 4 && oipcRedlinePdfStitchedRecord?.createdat_datetime) || - (itemid === 5 && oipcRedlineReviewPdfStitchedRecord?.createdat_datetime) + (itemid === 5 && oipcRedlineReviewPdfStitchedRecord?.createdat_datetime) || + (itemid === 6 && consultPDFStitchedRecord?.createdat_datetime) ); } @@ -2462,8 +2503,8 @@ export const RecordsLog = ({ {divisionFilters.map((division) => ( { export const calculateTotalUploadedFileSizeInKB = (records) => { return records?.reduce((total, record) => { - return ( - total + - (record.attributes.convertedfilesize - ? record.attributes.convertedfilesize - : record.attributes.filesize) - ); + return (total + record.attributes.filesize); }, 0); }; diff --git a/forms-flow-web/src/components/FOI/customComponents/StateDropDown.js b/forms-flow-web/src/components/FOI/customComponents/StateDropDown.js index 13f1e4ffd..42b9c6ca3 100644 --- a/forms-flow-web/src/components/FOI/customComponents/StateDropDown.js +++ b/forms-flow-web/src/components/FOI/customComponents/StateDropDown.js @@ -112,6 +112,12 @@ const StateDropDown = ({ appendedList.splice(-1, 0, recordsreadyforreview); return appendedList; } + const appendPreviousStateForHoldOthers = (stateList, previousStateName) => { + const previousStateObject = { status: previousStateName, isSelected: false }; + let appendedList = stateList.slice(); + appendedList.splice(-1, 0, previousStateObject); + return appendedList; + } const isMCFMinistryTeam = userDetail?.groups?.some(str => str.includes("MCF Ministry Team")) switch (_state.toLowerCase()) { case StateEnum.unopened.name.toLowerCase(): @@ -149,10 +155,10 @@ const StateDropDown = ({ case StateEnum.redirect.name.toLowerCase(): return _stateList.redirect; case StateEnum.callforrecords.name.toLowerCase(): - if (_isMinistryCoordinator && personalRequest) { + if (_isMinistryCoordinator) { if (isMCFMinistryTeam) { return appendRecordsReadyForReview(_stateList.callforrecordsforpersonal); - } else { + } else if (personalRequest) { return _stateList.callforrecordsforpersonal; } } @@ -200,6 +206,9 @@ const StateDropDown = ({ if (personalIAO) return _stateList.feeassessedforpersonal; return _stateList.feeassessed; case StateEnum.deduplication.name.toLowerCase(): + if (!isMCFMinistryTeam) { + return _stateList.deduplication.filter(_state => _state.status.toLowerCase() !== StateEnum.recordsreadyforreview.name.toLowerCase()); + } return _stateList.deduplication; case StateEnum.harms.name.toLowerCase(): return _stateList.harms; @@ -220,7 +229,10 @@ const StateDropDown = ({ break; case StateEnum.appfeeowing.name.toLowerCase(): return _stateList.appfeeowing; - + case StateEnum.onholdother.name.toLowerCase(): + if (!isMinistryCoordinator) { + return appendPreviousStateForHoldOthers(_stateList.onholdother, previousState); + } else return _stateList.onholdother; default: return []; } diff --git a/forms-flow-web/src/components/FOI/customComponents/statedropdown.scss b/forms-flow-web/src/components/FOI/customComponents/statedropdown.scss index 68e5048ba..06ac4642c 100644 --- a/forms-flow-web/src/components/FOI/customComponents/statedropdown.scss +++ b/forms-flow-web/src/components/FOI/customComponents/statedropdown.scss @@ -102,12 +102,13 @@ background-color: #096DD1; } - - .tagging { background-color: #9B1048; } .readytoscan{ background-color: #A2096C; +} +.onhold-other { + background-color: #595959; } \ No newline at end of file diff --git a/forms-flow-web/src/constants/FOI/enum.js b/forms-flow-web/src/constants/FOI/enum.js index 10eb7762e..35247b9d0 100644 --- a/forms-flow-web/src/constants/FOI/enum.js +++ b/forms-flow-web/src/constants/FOI/enum.js @@ -164,7 +164,8 @@ const MinistryNeedsScanning = [ const MinistryNeedsLANPages = [ "CFD", - "MCF" + "MCF", + "CAF" ] const RequestTypes = Object.freeze({ @@ -172,7 +173,7 @@ const RequestTypes = Object.freeze({ personal: "personal" }); -const MCFPopularSections = 23 +const MCFPopularSections = 21 const MSDPopularSections = 11 const RecordsDownloadList = [ @@ -182,6 +183,7 @@ const RecordsDownloadList = [ { id: 3, label: "Download Final Package", disabled: true }, { id: 4, label: "Download OIPC Redline for Sign Off", disabled: true }, { id: 5, label: "Download OIPC Redline for OIPC Review", disabled: true }, + { id: 6, label: "Download Consults", disabled: true }, ]; const RecordDownloadCategory = Object.freeze({ diff --git a/forms-flow-web/src/constants/FOI/foiministrygroupConstants.js b/forms-flow-web/src/constants/FOI/foiministrygroupConstants.js index 72d78c16d..0363ead51 100644 --- a/forms-flow-web/src/constants/FOI/foiministrygroupConstants.js +++ b/forms-flow-web/src/constants/FOI/foiministrygroupConstants.js @@ -4,6 +4,7 @@ const MINISTRYGROUPS = { AGR : "AGR Ministry Team", BRD : "BRD Ministry Team", CAS : "CAS Ministry Team", + CAF : "CAF Ministry Team", MCF : "MCF Ministry Team", CLB : "CLB Ministry Team", CITZ : "CITZ Ministry Team", @@ -41,7 +42,8 @@ const MINISTRYGROUPS = { TIC : "TIC Ministry Team", TRAN : "TRAN Ministry Team", COR : "COR Ministry Team", - HSG : "HSG Ministry Team" + HSG : "HSG Ministry Team", + LSB : "LSB Ministry Team" }; diff --git a/forms-flow-web/src/constants/FOI/statusEnum.js b/forms-flow-web/src/constants/FOI/statusEnum.js index 8b15ca80a..8783eaed5 100644 --- a/forms-flow-web/src/constants/FOI/statusEnum.js +++ b/forms-flow-web/src/constants/FOI/statusEnum.js @@ -28,11 +28,13 @@ const StateList = Object.freeze({ { status: "Open", isSelected: false }, { status: "Call For Records", isSelected: false }, { status: "Peer Review", isSelected: false }, + { status: "On Hold - Other", isSelected: false }, { status: "Closed", isSelected: false }, ], callforrecords: [ { status: "Call For Records", isSelected: false }, { status: "Open", isSelected: false }, + { status: "On Hold - Other", isSelected: false }, { status: "Closed", isSelected: false }, ], callforrecordscfdmsdpersonal: [ @@ -41,6 +43,7 @@ const StateList = Object.freeze({ { status: "Tagging", isSelected: false }, { status: "Ready to Scan", isSelected: false }, { status: "Records Ready for Review", isSelected: false }, + { status: "On Hold - Other", isSelected: false }, { status: "Closed", isSelected: false }, ], tagging: [ @@ -49,6 +52,7 @@ const StateList = Object.freeze({ { status: "Ready to Scan", isSelected: false }, { status: "Records Ready for Review", isSelected: false }, { status: "Records Review", isSelected: false }, + { status: "On Hold - Other", isSelected: false }, { status: "Closed", isSelected: false }, ], readytoscan: [ @@ -57,17 +61,20 @@ const StateList = Object.freeze({ { status: "Tagging", isSelected: false }, { status: "Records Ready for Review", isSelected: false }, { status: "Records Review", isSelected: false }, + { status: "On Hold - Other", isSelected: false }, { status: "Closed", isSelected: false }, ], feeassessed: [ { status: "Fee Estimate", isSelected: false }, { status: "On Hold", isSelected: false }, { status: "Call For Records", isSelected: false }, + { status: "On Hold - Other", isSelected: false }, { status: "Closed", isSelected: false }, ], feeassessedforpersonal: [ { status: "Fee Estimate", isSelected: false }, { status: "Call For Records", isSelected: false }, + { status: "On Hold - Other", isSelected: false }, { status: "Closed", isSelected: false }, ], onhold: [ @@ -80,10 +87,12 @@ const StateList = Object.freeze({ { status: "Deduplication", isSelected: false }, { status: "Harms Assessment", isSelected: false }, { status: "Records Review", isSelected: false }, + { status: "On Hold - Other", isSelected: false }, { status: "Closed", isSelected: false }, ], harms: [ { status: "Harms Assessment", isSelected: false }, + { status: "On Hold - Other", isSelected: false }, { status: "Closed", isSelected: false }, ], consult: [ @@ -92,6 +101,7 @@ const StateList = Object.freeze({ { status: "Records Review", isSelected: false }, { status: "Ministry Sign Off", isSelected: false }, { status: "Peer Review", isSelected: false }, + { status: "On Hold - Other", isSelected: false }, { status: "Closed", isSelected: false }, ], review: [ @@ -102,6 +112,7 @@ const StateList = Object.freeze({ { status: "Ministry Sign Off", isSelected: false }, { status: "Peer Review", isSelected: false }, { status: "Response", isSelected: false }, + { status: "On Hold - Other", isSelected: false }, { status: "Closed", isSelected: false }, ], reviewcfdmsdpersonal: [ @@ -113,10 +124,12 @@ const StateList = Object.freeze({ { status: "Ministry Sign Off", isSelected: false }, { status: "Peer Review", isSelected: false }, { status: "Response", isSelected: false }, + { status: "On Hold - Other", isSelected: false }, { status: "Closed", isSelected: false }, ], signoff: [ { status: "Ministry Sign Off", isSelected: false }, + { status: "On Hold - Other", isSelected: false }, { status: "Closed", isSelected: false }, ], response: [ @@ -124,24 +137,28 @@ const StateList = Object.freeze({ { status: "On Hold", isSelected: false }, { status: "Records Review", isSelected: false }, { status: "Peer Review", isSelected: false }, + { status: "On Hold - Other", isSelected: false }, { status: "Closed", isSelected: false }, ], responseforpersonal: [ { status: "Response", isSelected: false }, { status: "Records Review", isSelected: false }, { status: "Peer Review", isSelected: false }, + { status: "On Hold - Other", isSelected: false }, { status: "Closed", isSelected: false }, ], //peerreview: [{status:"Peer Review", isSelected: false},{status:"Intake in Progress", isSelected: false}, {status: "Open", isSelected: false},{status: "Records Review", isSelected: false},{status: "Consult", isSelected: false},{status: "Response", isSelected: false}], peerreview: [ { status: "Peer Review", isSelected: false }, - { status: "Records Ready for Review", isSelected: false } + { status: "Records Ready for Review", isSelected: false }, + { status: "On Hold - Other", isSelected: false }, ], section5pending: [ { status: "Section 5 Pending", isSelected: false }, { status: "Open", isSelected: false }, { status: "Peer Review", isSelected: false }, { status: "Redirect", isSelected: false }, + { status: "On Hold - Other", isSelected: false }, { status: "Closed", isSelected: false }, ], appfeeowing: [ @@ -149,6 +166,7 @@ const StateList = Object.freeze({ { status: "Open", isSelected: false }, { status: "Peer Review", isSelected: false }, { status: "Redirect", isSelected: false }, + { status: "On Hold - Other", isSelected: false }, { status: "Closed", isSelected: false }, ], recordsreadyforreview: [ @@ -157,8 +175,13 @@ const StateList = Object.freeze({ { status: "Tagging", isSelected: false }, { status: "Consult", isSelected: false }, { status: "Records Review", isSelected: false }, + { status: "On Hold - Other", isSelected: false }, { status: "Closed", isSelected: false } ], + onholdother: [ + { status: "On Hold - Other", isSelected: false }, + { status: "Closed", isSelected: false } + ] }); const MinistryStateList = Object.freeze({ @@ -205,6 +228,7 @@ const MinistryStateList = Object.freeze({ tagging: [{ status: "Tagging", isSelected: true }], readytoscan: [{ status: "Ready to Scan", isSelected: true }], recordsreadyforreview: [{ status: "Records Ready for Review", isSelected: false }], + onholdother:[{status: "On Hold - Other", isSelected: false }], }); // This corresponds to rows in the FOIRequestStatuses table on the backend @@ -231,6 +255,7 @@ const StateEnum = Object.freeze({ appfeeowing: { name: "App Fee Owing", label: "appfeeowing" }, section5pending: { name: "Section 5 Pending", label: "section5pending" }, recordsreadyforreview: { name: "Records Ready for Review", label: "recordsreadyforreview" }, + onholdother: { name: "On Hold - Other", label: "onholdother" }, }); const StateTransitionCategories = Object.freeze({ diff --git a/forms-flow-web/src/constants/constants.js b/forms-flow-web/src/constants/constants.js index bfb7ecf06..6e7315101 100644 --- a/forms-flow-web/src/constants/constants.js +++ b/forms-flow-web/src/constants/constants.js @@ -16,7 +16,7 @@ export const KEYCLOAK_REALM = export const KEYCLOAK_URL =(window._env_ && window._env_.REACT_APP_KEYCLOAK_URL) || process.env.REACT_APP_KEYCLOAK_URL; export const KEYCLOAK_AUTH_URL = `${KEYCLOAK_URL}/auth`; export const ANONYMOUS_USER = "anonymous"; -export const SESSION_SECURITY_KEY = "u7x!A%D*G-KaNdRgUkXp2s5v8y/B?E(H"; +export const SESSION_SECURITY_KEY = (window._env_ && window._env_.REACT_APP_SESSION_SECURITY_KEY) || process.env.REACT_APP_SESSION_SECURITY_KEY; //6 hour in milliseconds export const SESSION_LIFETIME = 21600000; export const SOCKETIO_CONNECT_URL = diff --git a/forms-flow-web/src/helper/FOI/helper.js b/forms-flow-web/src/helper/FOI/helper.js index f6051af89..78695a5a1 100644 --- a/forms-flow-web/src/helper/FOI/helper.js +++ b/forms-flow-web/src/helper/FOI/helper.js @@ -267,8 +267,6 @@ const getSessionData = (key) => { }; const addToFullnameList = (userArray, foiteam) => { - // console.log("userArray:",userArray) - // console.log("foiteam:",foiteam) if (!foiteam) return; @@ -320,9 +318,6 @@ const getFullnameList = () => { }; const getAssignToList = (team) => { - // console.log("team-session data:",(`${team.toLowerCase()}AssignToList`).replaceAll('"','')) - // console.log("getAssignToList() =>", getSessionData((`${team.toLowerCase()}AssignToList`).replaceAll('"',''))) - return getSessionData((`${team.toLowerCase()}AssignToList`).replaceAll('"','')) || []; }; @@ -335,7 +330,6 @@ const getMinistryRestrictedTagList = () => { }; const getIAOAssignToList = () => { - //console.log("getIAOAssignToList() =>",getSessionData("iaoAssignToList")) return getSessionData("iaoAssignToList"); }; @@ -490,17 +484,17 @@ const readUploadedFileAsBytes = (inputFile) => { }; const getCommentTypeIdByName = (commentTypes, name) => { - const commentType = commentTypes.find(type => type.name === name); + const commentType = commentTypes?.find(type => type.name === name); return commentType ? commentType.commenttypeid : 0; }; const getCommentLabelFromId = (commentTypes, id) => { - const commentType = commentTypes.find(type => type.commenttypeid === id); + const commentType = commentTypes?.find(type => type.commenttypeid === id); return commentType ? commentType.label?.toUpperCase() : ""; }; const getCommentTypeFromId = (commentTypes, id) => { - const commentType = commentTypes.find(type => type.commenttypeid === id); + const commentType = commentTypes?.find(type => type.commenttypeid === id); if(commentType != null && commentType != undefined){ if(commentType.name == "User submitted") return "general"; @@ -538,7 +532,6 @@ const setTeamTagList = (bcgovcode) => { if(bcgovcode !== null && bcgovcode !== undefined && bcgovcode !== 'iao'){ let ministryList= getAssignToList(bcgovcode) - //console.log("**ministryList:", ministryList) if(ministryList && ministryList?.length >0){ ministryList.forEach((team) => { team?.members.forEach((ministryUser) => { @@ -557,8 +550,6 @@ const setTeamTagList = (bcgovcode) => { }); } let _team = bcgovcode.toLowerCase().replace(/['"]+/g, ''); - //console.log("******_team*******",_team) - console.log("*************",fullnameArray) saveSessionData(`${_team}TagList`, fullnameArray); } @@ -567,8 +558,6 @@ const setTeamTagList = (bcgovcode) => { const getIAOTagList = (bcgovcode) => { let _team = bcgovcode.toLowerCase()?.replace(/['"]+/g, ''); - console.log("_team",_team) - console.log("=>",getSessionData(`${_team}TagList`)) return getSessionData(`${_team}TagList`) || []; }; diff --git a/forms-flow-web/src/modules/FOI/foiRequestsReducer.js b/forms-flow-web/src/modules/FOI/foiRequestsReducer.js index d5652f9bf..a5eaeab26 100644 --- a/forms-flow-web/src/modules/FOI/foiRequestsReducer.js +++ b/forms-flow-web/src/modules/FOI/foiRequestsReducer.js @@ -60,11 +60,13 @@ const initialState = { foiPDFStitchedRecordForOipcRedlineReview: {}, foiPDFStitchedRecordForOipcRedline: {}, foiPDFStitchedRecordForResponsePackage: {}, + foiPDFStitchedRecordForConsultPackage: {}, foiPDFStitchStatusForHarms: "not started", foiPDFStitchStatusForRedlines: "not started", foiPDFStitchStatusForResponsePackage: "not started", foiPDFStitchStatusForOipcRedlineReview: "not started", foiPDFStitchStatusForOipcRedline: "not started", + foiPDFStitchStatusForConsults: "not started", foiRequestCFRForm: { overallsuggestions: "", status: "init", @@ -291,6 +293,8 @@ const foiRequests = (state = initialState, action) => { ...state, foiPDFStitchedRecordForOipcRedline: action.payload, }; + case FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_RECORD_FOR_CONSULTS: + return { ...state, foiPDFStitchedRecordForConsultPackage: action.payload }; case FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_STATUS_FOR_HARMS: return { ...state, foiPDFStitchStatusForHarms: action.payload }; case FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_STATUS_FOR_REDLINES: @@ -301,6 +305,8 @@ const foiRequests = (state = initialState, action) => { return { ...state, foiPDFStitchStatusForOipcRedlineReview: action.payload }; case FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_STATUS_FOR_OIPCREDLINE: return { ...state, foiPDFStitchStatusForOipcRedline: action.payload }; + case FOI_ACTION_CONSTANTS.FOI_PDF_STITCHED_STATUS_FOR_CONSULTS: + return { ...state, foiPDFStitchStatusForConsults: action.payload }; case FOI_ACTION_CONSTANTS.FOI_REQUEST_CFR_FORM: return { ...state, diff --git a/notification-manager/notification_api/dao/models/FOIRequestComments.py b/notification-manager/notification_api/dao/models/FOIRequestComments.py index bf06b1286..72fdfcd46 100644 --- a/notification-manager/notification_api/dao/models/FOIRequestComments.py +++ b/notification-manager/notification_api/dao/models/FOIRequestComments.py @@ -24,7 +24,7 @@ class Meta: # pylint: disable=too-few-public-methods @classmethod - def savecomment(cls, commenttypeid, foirequestcomment, userid): + def savecomment(cls, commenttypeid, foirequestcomment, userid, createdat): conn = None try: id_of_new_row = None @@ -39,7 +39,7 @@ def savecomment(cls, commenttypeid, foirequestcomment, userid): comment, taggedusers, isactive, createdby, created_at, commentsversion) \ VALUES(%s::integer,%s::integer, %s::integer, %s::integer,%s,%s,%s::boolean,%s,%s,%s::integer) RETURNING commentid', (parentcommentid, int(data["ministryrequestid"]), int(data["version"]), commenttypeid, - str(data["comment"]), taggedusers, True, userid, datetime.now(), data["commentsversion"])) + str(data["comment"]), taggedusers, True, userid, createdat or datetime.now(), data["commentsversion"])) conn.commit() id_of_new_row = cursor.fetchone()[0] cursor.close() diff --git a/notification-manager/notification_api/io/message/processor/notificationprocessor.py b/notification-manager/notification_api/io/message/processor/notificationprocessor.py index 9cce87ac3..507fe68c0 100644 --- a/notification-manager/notification_api/io/message/processor/notificationprocessor.py +++ b/notification-manager/notification_api/io/message/processor/notificationprocessor.py @@ -88,6 +88,7 @@ def __createcomment(self, notification): comment, notification.createdby, 2, + notification.__dict__.get('createdat') ) def __notificationmessage(self, username): @@ -137,6 +138,15 @@ def __createnotificationforresponse(self, notification): ) def __createcommentforresponse(self, notification): + if notification.feeoverridereason is not None and notification.feeoverridereason != '': + comment = {"comment": notification.feeoverridereason} + commentservice().createcomment( + "ministryrequest", + notification.ministryrequestid, + comment, + notification.createdby, + 2, + ) comment = {"comment": self.__createresponsemessage(notification.errorflag)} return commentservice().createcomment( "ministryrequest", @@ -164,7 +174,7 @@ def __createcommentforredline(self, notification): notification.createdby, 2, ) - + def __createresponsemessage(self, errorflag): if errorflag == "YES": return "Creating the Release Package failed. Please try again" diff --git a/notification-manager/notification_api/io/message/schemas/notification.py b/notification-manager/notification_api/io/message/schemas/notification.py index ced8fa5da..7094554c3 100644 --- a/notification-manager/notification_api/io/message/schemas/notification.py +++ b/notification-manager/notification_api/io/message/schemas/notification.py @@ -14,6 +14,7 @@ class NotificationPublishSchema(object): serviceid = fields.Str(data_key="serviceid", allow_none=False) errorflag = fields.Str(data_key="errorflag", allow_none=False) createdby = fields.Str(data_key="message", allow_none=False) + createdat = fields.Str(data_key="createdat", allow_none=True, required=False) class NotificationHarmsPDFStitchPublishSchema(object): @@ -34,3 +35,4 @@ class NotificationRedlineResponsePDFStitchPublishSchema(object): serviceid = fields.Str(data_key="serviceid", allow_none=False) errorflag = fields.Str(data_key="errorflag", allow_none=False) createdby = fields.Str(data_key="message", allow_none=False) + feeoverridereason= fields.Str(data_key="feeoverridereason", allow_none=True) diff --git a/notification-manager/notification_api/io/redis_stream/redisstreamdb.py b/notification-manager/notification_api/io/redis_stream/redisstreamdb.py index d43a16ee8..03341027a 100644 --- a/notification-manager/notification_api/io/redis_stream/redisstreamdb.py +++ b/notification-manager/notification_api/io/redis_stream/redisstreamdb.py @@ -2,4 +2,5 @@ from config import REDIS_HOST,REDIS_PORT,REDIS_PASSWORD, REDIS_HEALTH_CHECK_INTERVAL #streamdb = Database(host=str(REDIS_HOST), port=str(REDIS_PORT), db=0,password=str(REDIS_PASSWORD)) +print(REDIS_HOST) streamdb = Database(host=str(REDIS_HOST), port=str(REDIS_PORT), db=0,password=str(REDIS_PASSWORD), retry_on_timeout=True, health_check_interval=int(REDIS_HEALTH_CHECK_INTERVAL), socket_keepalive=True) diff --git a/notification-manager/notification_api/services/commentservice.py b/notification-manager/notification_api/services/commentservice.py index 5155ff1b8..0d8195353 100644 --- a/notification-manager/notification_api/services/commentservice.py +++ b/notification-manager/notification_api/services/commentservice.py @@ -16,10 +16,10 @@ class commentservice: """ - def createcomment(self, requesttype, requestid, comment, userid, type=1): + def createcomment(self, requesttype, requestid, comment, userid, type=1, createdat=datetime.now()): foirequest = self.getrequest(requestid, requesttype) _comment = self.__preparecomment(foirequest, comment) - FOIRequestComment().savecomment(type, _comment, userid) + FOIRequestComment().savecomment(type, _comment, userid, createdat) return DefaultMethodResult(True,'No change',requestid) def __preparecomment(self, foirequest, comment): diff --git a/request-management-api/migrations/versions/06283c0685fb_update_cfd_personal_tags.py b/request-management-api/migrations/versions/06283c0685fb_update_cfd_personal_tags.py new file mode 100644 index 000000000..6aa2424e8 --- /dev/null +++ b/request-management-api/migrations/versions/06283c0685fb_update_cfd_personal_tags.py @@ -0,0 +1,43 @@ +"""update CFD Personal tags + +Revision ID: 06283c0685fb +Revises: aa2691fa6c3c +Create Date: 2024-08-14 12:40:37.844463 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '06283c0685fb' +down_revision = 'aa2691fa6c3c' +branch_labels = None +depends_on = None + + +def upgrade(): + filetypes = ["CS","FS","ICM","CYMH","RE","CYSN","AD_C","DIV","AA","AH","AO","FH","MAPLES","SP","PABS","VAN-AA","VAN-CAS","VAN-CIC","VAN-CCAS","VIC-AA","YAG","Autism Case File","Assessment & Resource","AR ","AS","AM","AP","CC","Choices","CIC","CS UNREG","CT","CH","FS UNREG","RE UNREG","SN","Woodlands","Incident","Memo ","Service Request","FS Case","CS Case","SR Case","Complaint"] + ftsortorder = 1 + + op.execute('UPDATE public."ProgramAreaDivisions" SET isactive = FALSE WHERE programareaid in (SELECT programareaid FROM public."ProgramAreas" WHERE iaocode =\'CFD\') AND type = \'filetype\'') + for ftype in filetypes: + op.execute('INSERT INTO public."ProgramAreaDivisions"(programareaid, name, isactive, created_at, createdby, sortorder, issection, specifictopersonalrequests, type)\ + VALUES ((SELECT programareaid FROM public."ProgramAreas" WHERE iaocode =\'CFD\'), \''+ftype+'\', TRUE, NOW(), \'system\', '+ str(ftsortorder) +', FALSE, TRUE, \'filetype\');') + ftsortorder = ftsortorder+1 + + + sections = ["Accountability","Activity Forms","Adoption","ADR","Agreements and Approvals","Caregiver Information","Case Conference","Case Notes","Case Snapshot","Change Card and Forms","Child and Birth Family Background","Child in Care Information","Collaborative Planning","Consents and Authorizations","Contracts","Correspondence","Cultural Planning","Documents","Education, Employment and Training","External Assessments","Family Group Mediation","File Summary","Financial","Incidents","Internal Assessments","Inside Back Cover","Inside Front Cover","Intake and Investigation","Legal","Maples","Mediation","Medical","Note Pad Screens","Out-of-Care Services","Personal History and Records","Physical File Summary","Placement Slips","Planning","Protocol and Incidents","Reconsideration","Running Record","Referrals","Relief Care Giver Documentation","Reports","Reviews","Services for Children Not in Care","Supervisor Orders","Young Offenders"] + secsortorder = 1 + + op.execute('UPDATE public."ProgramAreaDivisions" SET isactive = FALSE WHERE programareaid in (SELECT programareaid FROM public."ProgramAreas" WHERE iaocode =\'CFD\') AND type = \'section\' AND name != \'TBD\'') + for sec in sections: + op.execute('INSERT INTO public."ProgramAreaDivisions"(programareaid, name, isactive, created_at, createdby, sortorder, issection, specifictopersonalrequests, type)\ + VALUES ((SELECT programareaid FROM public."ProgramAreas" WHERE iaocode =\'CFD\'), \''+sec+'\', TRUE, NOW(), \'system\', '+ str(secsortorder) +', TRUE, TRUE, \'section\');') + secsortorder = secsortorder+1 + + op.execute('UPDATE public."ProgramAreaDivisions" SET sortorder = '+str(secsortorder)+' WHERE programareaid in (SELECT programareaid FROM public."ProgramAreas" WHERE iaocode =\'CFD\') AND type = \'section\' AND name = \'TBD\'') + +def downgrade(): + op.execute('UPDATE public."ProgramAreaDivisions" SET isactive = FALSE WHERE programareaid in (SELECT programareaid FROM public."ProgramAreas" WHERE iaocode =\'CFD\') AND type = \'filetype\'') + op.execute('UPDATE public."ProgramAreaDivisions" SET isactive = FALSE WHERE programareaid in (SELECT programareaid FROM public."ProgramAreas" WHERE iaocode =\'CFD\') AND type = \'section\' AND name != \'TBD\'') \ No newline at end of file diff --git a/request-management-api/migrations/versions/1d60153653db_update_cfd_personal_sections_sorting_.py b/request-management-api/migrations/versions/1d60153653db_update_cfd_personal_sections_sorting_.py new file mode 100644 index 000000000..c296cbf22 --- /dev/null +++ b/request-management-api/migrations/versions/1d60153653db_update_cfd_personal_sections_sorting_.py @@ -0,0 +1,32 @@ +"""Update CFD Personal Sections Sorting Order + +Revision ID: 1d60153653db +Revises: 06283c0685fb +Create Date: 2024-08-19 09:36:01.403157 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '1d60153653db' +down_revision = '06283c0685fb' +branch_labels = None +depends_on = None + + +def upgrade(): + sections = ["Activity Forms","Adoption","Case Notes","Change Card and Forms","Collaborative Planning","Correspondence","Cultural Planning","Education, Employment and Training","External Assessments","Family Group Mediation","Financial","Incidents","Internal Assessments","Inside Back Cover","Inside Front Cover","Intake and Investigation","Legal","Medical","Personal History and Records","Young Offenders","Accountability","ADR","Agreements and Approvals","Caregiver Information","Case Conference","Case Snapshot","Child and Birth Family Background","Child in Care Information","Consents and Authorizations","Contracts","Documents","File Summary","Maples","Mediation","Note Pad Screens","Out-of-Care Services","Physical File Summary","Placement Slips","Planning","Protocol and Incidents","Reconsideration","Running Record","Referrals","Relief Care Giver Documentation","Reports","Reviews","Services for Children Not in Care","Supervisor Orders"] + secsortorder = 1 + + op.execute('UPDATE public."ProgramAreaDivisions" SET isactive = FALSE WHERE programareaid in (SELECT programareaid FROM public."ProgramAreas" WHERE iaocode =\'CFD\') AND type = \'section\' AND name != \'TBD\'') + for sec in sections: + op.execute('INSERT INTO public."ProgramAreaDivisions"(programareaid, name, isactive, created_at, createdby, sortorder, issection, specifictopersonalrequests, type)\ + VALUES ((SELECT programareaid FROM public."ProgramAreas" WHERE iaocode =\'CFD\'), \''+sec+'\', TRUE, NOW(), \'system\', '+ str(secsortorder) +', TRUE, TRUE, \'section\');') + secsortorder = secsortorder+1 + + op.execute('UPDATE public."ProgramAreaDivisions" SET sortorder = '+str(secsortorder)+' WHERE programareaid in (SELECT programareaid FROM public."ProgramAreas" WHERE iaocode =\'CFD\') AND type = \'section\' AND name = \'TBD\'') + +def downgrade(): + op.execute('UPDATE public."ProgramAreaDivisions" SET isactive = FALSE WHERE programareaid in (SELECT programareaid FROM public."ProgramAreas" WHERE iaocode =\'CFD\') AND type = \'section\' AND name != \'TBD\'') \ No newline at end of file diff --git a/request-management-api/migrations/versions/3a2ffb0af202_.py b/request-management-api/migrations/versions/3a2ffb0af202_.py new file mode 100644 index 000000000..344139ed0 --- /dev/null +++ b/request-management-api/migrations/versions/3a2ffb0af202_.py @@ -0,0 +1,31 @@ +"""empty message + +Revision ID: 3a2ffb0af202 +Revises: efb8bc09d7ac +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 = '3a2ffb0af202' +down_revision = 'efb8bc09d7ac' + +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.execute('ALTER TABLE public."FOIRawRequestDocuments" ALTER COLUMN filename TYPE character varying(500);') + op.execute('ALTER TABLE public."FOIMinistryRequestDocuments" ALTER COLUMN filename TYPE character varying(500);') + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.execute('ALTER TABLE public."FOIRawRequestDocuments" ALTER COLUMN filename TYPE character varying(120);') + op.execute('ALTER TABLE public."FOIMinistryRequestDocuments" ALTER COLUMN filename TYPE character varying(120);') + # ### end Alembic commands ### diff --git a/request-management-api/migrations/versions/719e5289e6f8_.py b/request-management-api/migrations/versions/719e5289e6f8_.py index 485a7276f..5772262dc 100644 --- a/request-management-api/migrations/versions/719e5289e6f8_.py +++ b/request-management-api/migrations/versions/719e5289e6f8_.py @@ -1,7 +1,7 @@ """empty message Revision ID: 719e5289e6f8 -Revises: 5fdd5df3d642 +Revises: 1d60153653db Create Date: 2024-08-13 08:37:41.321684 """ @@ -13,7 +13,7 @@ # revision identifiers, used by Alembic. revision = '719e5289e6f8' -down_revision = 'aa2691fa6c3c' +down_revision = '1d60153653db' branch_labels = None depends_on = None diff --git a/request-management-api/migrations/versions/83cfc8047acf_.py b/request-management-api/migrations/versions/83cfc8047acf_.py new file mode 100644 index 000000000..d5de5515c --- /dev/null +++ b/request-management-api/migrations/versions/83cfc8047acf_.py @@ -0,0 +1,41 @@ +"""empty message + +Revision ID: 83cfc8047acf +Revises: bbee01df3e8d +Create Date: 2024-10-31 12:47:04.379106 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.sql import column, table +from sqlalchemy.sql.sqltypes import Boolean, String + +# revision identifiers, used by Alembic. +revision = '83cfc8047acf' +down_revision = 'bbee01df3e8d' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + requeststatus_table = table('FOIRequestStatuses', + column('name',String), + column('description',String), + column('isactive',Boolean), + column('statuslabel',String), + ) + op.bulk_insert( + requeststatus_table, + [ + {'name':'On Hold - Other','description':'On Hold for Other reasons','isactive':True, 'statuslabel':'onholdother'}, + ] + ) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.execute('delete from public."FOIRequestStatuses" where name = \'On Hold - Other\';') + # ### end Alembic commands ### + diff --git a/request-management-api/migrations/versions/bbee01df3e8d_.py b/request-management-api/migrations/versions/bbee01df3e8d_.py new file mode 100644 index 000000000..2ff91c68b --- /dev/null +++ b/request-management-api/migrations/versions/bbee01df3e8d_.py @@ -0,0 +1,29 @@ +"""empty message + +Revision ID: bbee01df3e8d +Revises: 3a2ffb0af202 +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 = 'bbee01df3e8d' +down_revision = '3a2ffb0af202' + +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.execute('''INSERT INTO public."SubjectCodes" (name, description, isaxissubjectcode, isactive) VALUES ('CFD Re-print', 'CFD Re-print', true, true);''') + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.execute('''DELETE FROM public."SubjectCodes" WHERE name = 'CFD Re-print';''') + # ### end Alembic commands ### diff --git a/request-management-api/migrations/versions/ec27defe9178_CAF_ministry.py b/request-management-api/migrations/versions/ec27defe9178_CAF_ministry.py new file mode 100644 index 000000000..c02c5c1c3 --- /dev/null +++ b/request-management-api/migrations/versions/ec27defe9178_CAF_ministry.py @@ -0,0 +1,56 @@ +"""empty message + +Revision ID: ec27defe9178 +Revises: 719e5289e6f8 +Create Date: 2024-09-06 19:46:07.867757 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'ec27defe9178' +down_revision = '719e5289e6f8' +branch_labels = None +depends_on = None + + +def upgrade(): + op.execute('''INSERT INTO public."ProgramAreas"(name, type, isactive, bcgovcode, iaocode) VALUES ('Ministry of Children and Family Development (Generals)', 'BC GOV Ministry', True, 'CAF', 'CAF');commit;''') + + # op.execute('''INSERT INTO public."ProgramAreaDivisions"( + # programareaid, name, isactive, created_at, createdby, sortorder, updated_at, updatedby, issection, parentid, specifictopersonalrequests, type) + # SELECT + # (select programareaid from public."ProgramAreas" where bcgovcode='CAF'), name, isactive, created_at, createdby, sortorder, updated_at, updatedby, issection, parentid, specifictopersonalrequests, type + # FROM public."ProgramAreaDivisions" + # where programareaid = (select programareaid from public."ProgramAreas" where bcgovcode = 'MCF') + # and specifictopersonalrequests is false + # and isactive = true + # ORDER BY divisionid ASC ''') + + op.execute('''INSERT INTO public."OperatingTeams"(name, description, isactive, type) VALUES ('CAF Ministry Team', 'CAF Ministry Team', True, 'ministry');commit;''') + + op.execute('''INSERT INTO public."FOIRequestTeams"( + requesttype, requeststatusid, teamid, programareaid, isactive, requeststatuslabel) + SELECT + requesttype, requeststatusid, + case when ot.name = 'MCF Ministry Team' + then (select teamid from public."OperatingTeams" where name = 'CAF Ministry Team') + else (rt.teamid) end, + (select programareaid from public."ProgramAreas" where bcgovcode = 'CAF'), rt.isactive, requeststatuslabel + FROM public."FOIRequestTeams" rt + join public."OperatingTeams" ot on rt.teamid = ot.teamid + where + programareaid = (select programareaid from public."ProgramAreas" where bcgovcode = 'MCF') and + requesttype = 'General' and rt.isactive = true''') + +def downgrade(): + op.execute('''delete from public."FOIRequestTeams" where programareaid in (select programareaid from public."ProgramAreas" where bcgovcode = 'CAF')''') + + op.execute('''delete from public."OperatingTeams" where name = 'CAF Ministry Team' ''') + + # op.execute('''delete from public."ProgramAreaDivisions" where programareaid in (select programareaid from public."ProgramAreas" where bcgovcode = 'CAF')''') + + op.execute('''delete from public."ProgramAreas" where bcgovcode = 'CAF' ''') +# \ No newline at end of file diff --git a/request-management-api/migrations/versions/efb8bc09d7ac_.py b/request-management-api/migrations/versions/efb8bc09d7ac_.py new file mode 100644 index 000000000..01c171d23 --- /dev/null +++ b/request-management-api/migrations/versions/efb8bc09d7ac_.py @@ -0,0 +1,24 @@ +"""ADD NEW PROGRAM AREA (LSB) + +Revision ID: efb8bc09d7ac +Revises: ec27defe9178 +Create Date: 2024-10-28 13:54:56.964072 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = 'efb8bc09d7ac' +down_revision = 'ec27defe9178' +branch_labels = None +depends_on = None + + +def upgrade(): + op.execute('''INSERT INTO public."ProgramAreas" (name, type, isactive, bcgovcode, iaocode) VALUES ('Legal Services Branch', 'Other', True, 'LSB', 'LSB'); commit;''') + + +def downgrade(): + op.execute('''DELETE FROM public."ProgramAreas" WHERE bcgovcode = 'LSB'; commit;''') diff --git a/request-management-api/request_api/models/CloseReasons.py b/request-management-api/request_api/models/CloseReasons.py index 729bc779a..1fb9a0523 100644 --- a/request-management-api/request_api/models/CloseReasons.py +++ b/request-management-api/request_api/models/CloseReasons.py @@ -21,7 +21,7 @@ def getallclosereasons(cls): @classmethod def getclosereason(cls,closereasonid): - closereason_schema = CloseReasonSchema(many=True) + closereason_schema = CloseReasonSchema(many=False) query = db.session.query(CloseReason).filter_by(closereasonid=closereasonid).first() return closereason_schema.dump(query) diff --git a/request-management-api/request_api/models/FOIMinistryRequestDocuments.py b/request-management-api/request_api/models/FOIMinistryRequestDocuments.py index 3acdb80f2..f49f53c14 100644 --- a/request-management-api/request_api/models/FOIMinistryRequestDocuments.py +++ b/request-management-api/request_api/models/FOIMinistryRequestDocuments.py @@ -19,7 +19,7 @@ class FOIMinistryRequestDocument(db.Model): # Defining the columns foiministrydocumentid = db.Column(db.Integer, primary_key=True,autoincrement=True) documentpath = db.Column(db.String(1000), unique=False, nullable=False) - filename = db.Column(db.String(120), unique=False, nullable=True) + filename = db.Column(db.String(500), unique=False, nullable=True) category = db.Column(db.String(120), unique=False, nullable=True) version =db.Column(db.Integer, nullable=True) isactive = db.Column(db.Boolean, unique=False, nullable=False,default=True) @@ -48,14 +48,19 @@ def getdocuments(cls,ministryrequestid,ministryrequestversion): @classmethod def getactivedocuments(cls,ministryrequestid): sql = ''' - WITH document AS ( + WITH rawdocument AS ( + SELECT documentpath, min(foidocumentid) as foidocumentid + FROM "FOIRawRequestDocuments" + GROUP BY documentpath + ), + document AS ( SELECT documentpath, min(created_at) AS created_at FROM "FOIMinistryRequestDocuments" GROUP BY documentpath ) SELECT * FROM ( SELECT DISTINCT ON (foiministrydocumentid) - doc.created_at, + case when rrd.created_at is null then doc.created_at else rrd.created_at end, fmrd.foiministrydocumentid, fmrd.filename, fmrd.documentpath, @@ -67,7 +72,10 @@ def getactivedocuments(cls,ministryrequestid): FROM "FOIMinistryRequestDocuments" fmrd JOIN document doc on doc.documentpath = fmrd.documentpath - where fmrd.foiministryrequest_id =:ministryrequestid ORDER BY fmrd.foiministrydocumentid, version DESC) AS list + left JOIN rawdocument rawdoc + on rawdoc.documentpath = fmrd.documentpath + left join "FOIRawRequestDocuments" rrd on rrd.foidocumentid = rawdoc.foidocumentid + where fmrd.foiministryrequest_id = :ministryrequestid ORDER BY fmrd.foiministrydocumentid, version DESC) AS list ORDER BY created_at DESC ''' rs = db.session.execute(text(sql), {'ministryrequestid': ministryrequestid}) diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index 0c352a3bb..be13ad168 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -175,11 +175,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.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() + _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,StateName.onholdother.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.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() + _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,StateName.onholdother.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.requeststatuslabel.in_([StateName.callforrecords.name,StateName.recordsreview.name,StateName.recordsreadyforreview.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() + _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.recordsreadyforreview.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,StateName.onholdother.name]))))).all() _requests = [] ministryrequest_schema = FOIMinistryRequestSchema() @@ -332,7 +332,7 @@ def getstatesummary(cls, ministryrequestid): return transitions @classmethod - def getlastoffholddate(cls, ministryrequestid): + def getlastoffholddate(cls, ministryrequestid, currentstatus): transitions = [] try: sql = """select fm2.version, fs2."name" as status, fm2.created_at from "FOIMinistryRequests" fm2 inner join "FOIRequestStatuses" fs2 on fm2.requeststatusid = fs2.requeststatusid @@ -349,7 +349,7 @@ def getlastoffholddate(cls, ministryrequestid): recent_offhold_index = None offhold_indicator = False for entry in desc_transitions: - if entry["status"] == StateName.onhold.value: + if entry["status"] == currentstatus: onhold_occurance = onhold_occurance + 1 if onhold_occurance > 1: recent_offhold_index = index @@ -432,20 +432,25 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us ministry_restricted_requests = aliased(FOIRestrictedMinistryRequest) #filter/search + _keywords = [] + if(keyword is not None): + _keywords = keyword.lower().replace(",", " ").split() if(len(filterfields) > 0 and keyword is not None): - filtercondition = [] - - if(keyword != "restricted"): - for field in filterfields: - filtercondition.append(FOIMinistryRequest.findfield(field, iaoassignee, ministryassignee).ilike('%'+keyword+'%')) - else: - if(requestby == 'IAO'): - filtercondition.append(FOIRestrictedMinistryRequest.isrestricted == True) + for _keyword in _keywords: + onekeywordfiltercondition = [] + if(_keyword != "restricted"): + for field in filterfields: + onekeywordfiltercondition.append(FOIMinistryRequest.findfield(field, iaoassignee, ministryassignee).ilike('%'+_keyword+'%')) else: - filtercondition.append(ministry_restricted_requests.isrestricted == True) - if (keyword.lower() == "oipc"): - filtercondition.append(FOIMinistryRequest.isoipcreview == True) + if(requestby == 'IAO'): + onekeywordfiltercondition.append(FOIRestrictedMinistryRequest.isrestricted == True) + else: + onekeywordfiltercondition.append(ministry_restricted_requests.isrestricted == True) + if (_keyword == "oipc"): + onekeywordfiltercondition.append(FOIMinistryRequest.isoipcreview == True) + + filtercondition.append(or_(*onekeywordfiltercondition)) intakesorting = case([ (and_(FOIMinistryRequest.assignedto == None, FOIMinistryRequest.assignedgroup == 'Intake Team'), # Unassigned requests first @@ -486,13 +491,13 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us else_ = FOIMinistryRequest.assignedministrygroup).label('ministryAssignedToFormatted') duedate = case([ - (FOIMinistryRequest.requeststatuslabel == StateName.onhold.name, # On Hold + (or_(FOIMinistryRequest.requeststatuslabel == StateName.onhold.name, FOIMinistryRequest.requeststatuslabel == StateName.onholdother.name), # On Hold literal(None)), ], else_ = cast(FOIMinistryRequest.duedate, String)).label('duedate') cfrduedate = case([ - (FOIMinistryRequest.requeststatuslabel == StateName.onhold.name, # On Hold + (or_(FOIMinistryRequest.requeststatuslabel == StateName.onhold.name, FOIMinistryRequest.requeststatuslabel == StateName.onholdother.name), # On Hold literal(None)), ], else_ = cast(FOIMinistryRequest.cfrduedate, String)).label('cfrduedate') @@ -706,7 +711,7 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us if(keyword is None): return dbquery else: - return dbquery.filter(or_(*filtercondition)) + return dbquery.filter(and_(*filtercondition)) @classmethod def getrequestspagination(cls, group, page, size, sortingitems, sortingorders, filterfields, keyword, additionalfilter, userid, isiaorestrictedfilemanager, isministryrestrictedfilemanager): @@ -841,7 +846,7 @@ def getgroupfilters(cls, groups): ) ) ) - statusfilter = 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, StateName.recordsreadyforreview.name]) + statusfilter = 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, StateName.recordsreadyforreview.name, StateName.onholdother.name]) ministryfilter = and_( FOIMinistryRequest.isactive == True, FOIRequestStatus.isactive == True, @@ -889,7 +894,7 @@ def getupcominglegislativeduerecords(cls): where isactive = true and duedate is not null and requeststatuslabel not in :requeststatuslabel and duedate between NOW() - INTERVAL '7 DAY' AND NOW() + INTERVAL '7 DAY' order by filenumber , version desc;""" - requeststatuslabel = tuple([StateName.closed.name,StateName.redirect.name,StateName.unopened.name,StateName.intakeinprogress.name,StateName.onhold.name,StateName.archived.name]) + requeststatuslabel = tuple([StateName.closed.name,StateName.redirect.name,StateName.unopened.name,StateName.intakeinprogress.name,StateName.onhold.name,StateName.archived.name, StateName.onholdother.name]) rs = db.session.execute(text(sql), {'requeststatuslabel': requeststatuslabel}) for row in rs: upcomingduerecords.append({"filenumber": row["filenumber"], "duedate": row["duedate"],"foiministryrequestid": row["foiministryrequestid"], "version": row["version"], "foirequest_id": row["foirequest_id"], "created_at": row["created_at"], "createdby": row["createdby"]}) @@ -915,7 +920,7 @@ def getupcomingdivisionduerecords(cls): inner join "ProgramAreaDivisionStages" pads on frd.stageid = pads.stageid and frd.stageid in (5, 7, 9) and frd.divisionduedate between NOW() - INTERVAL '7 DAY' AND NOW() + INTERVAL '7 DAY' order by frd.foiministryrequest_id , frd.foiministryrequestversion_id desc;""" - requeststatuslabel = tuple([StateName.closed.name,StateName.redirect.name,StateName.unopened.name,StateName.intakeinprogress.name,StateName.onhold.name,StateName.archived.name]) + requeststatuslabel = tuple([StateName.closed.name,StateName.redirect.name,StateName.unopened.name,StateName.intakeinprogress.name,StateName.onhold.name,StateName.archived.name,StateName.onholdother.name]) rs = db.session.execute(text(sql), {'requeststatuslabel': requeststatuslabel}) for row in rs: @@ -1108,13 +1113,13 @@ def getbasequery(cls, iaoassignee, ministryassignee, userid=None, requestby='IAO else_ = FOIMinistryRequest.assignedministrygroup).label('ministryAssignedToFormatted') duedate = case([ - (FOIMinistryRequest.requeststatuslabel == StateName.onhold.name, # On Hold + (or_(FOIMinistryRequest.requeststatuslabel == StateName.onhold.name, FOIMinistryRequest.requeststatuslabel == StateName.onholdother.name), # On Hold literal(None)), ], else_ = cast(FOIMinistryRequest.duedate, String)).label('duedate') cfrduedate = case([ - (FOIMinistryRequest.requeststatuslabel == StateName.onhold.name, # On Hold + (or_(FOIMinistryRequest.requeststatuslabel == StateName.onhold.name, FOIMinistryRequest.requeststatuslabel == StateName.onholdother.name), # On Hold literal(None)), ], else_ = cast(FOIMinistryRequest.cfrduedate, String)).label('cfrduedate') @@ -1323,7 +1328,7 @@ def advancedsearch(cls, params, userid, isministryrestrictedfilemanager = False) groupfilter.append(FOIMinistryRequest.assignedministrygroup == group) #ministry advanced search show cfr onwards - 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,StateName.recordsreadyforreview.name]) + 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,StateName.recordsreadyforreview.name,StateName.onholdother.name]) ministry_queue = FOIMinistryRequest.advancedsearchsubquery(params, iaoassignee, ministryassignee, userid, 'Ministry', False, isministryrestrictedfilemanager).filter(and_(or_(*groupfilter), statefilter)) @@ -1408,8 +1413,8 @@ def getfilterforrequeststatus(cls, params, iaoassignee, ministryassignee): #request status: overdue || on time if(params['requeststatus'][0] == 'overdue'): #exclude "on hold" for overdue - statelabel = StateName.onhold.name - return and_(FOIMinistryRequest.findfield('duedate', iaoassignee, ministryassignee) < datetime.now().date(), FOIMinistryRequest.requeststatuslabel != statelabel) + # statelabel = StateName.onhold.name + return and_(FOIMinistryRequest.findfield('duedate', iaoassignee, ministryassignee) < datetime.now().date(), and_(FOIMinistryRequest.requeststatuslabel != StateName.onhold.name, FOIMinistryRequest.requeststatuslabel != StateName.onholdother.name)) else: return FOIMinistryRequest.findfield('duedate', iaoassignee, ministryassignee) >= datetime.now().date() diff --git a/request-management-api/request_api/models/FOIRawRequestDocuments.py b/request-management-api/request_api/models/FOIRawRequestDocuments.py index 465e3a2cf..7d75b4140 100644 --- a/request-management-api/request_api/models/FOIRawRequestDocuments.py +++ b/request-management-api/request_api/models/FOIRawRequestDocuments.py @@ -19,7 +19,7 @@ class FOIRawRequestDocument(db.Model): # Defining the columns foidocumentid = db.Column(db.Integer, primary_key=True,autoincrement=True) documentpath = db.Column(db.String(1000), unique=False, nullable=False) - filename = db.Column(db.String(120), unique=False, nullable=True) + filename = db.Column(db.String(500), unique=False, nullable=True) category = db.Column(db.String(120), unique=False, nullable=True) version =db.Column(db.Integer, nullable=True) isactive = db.Column(db.Boolean, unique=False, nullable=False,default=True) @@ -37,7 +37,21 @@ class FOIRawRequestDocument(db.Model): def getdocuments(cls,requestid, requestversion): documents = [] try: - sql = 'SELECT * FROM (SELECT DISTINCT ON (foidocumentid) raw2.created_at, raw.created_at as current_version_created_at, raw.foidocumentid, raw.filename, raw.documentpath, raw.category, raw.isactive, raw.createdby FROM "FOIRawRequestDocuments" raw join "FOIRawRequestDocuments" raw2 on (raw.foirequest_id = raw2.foirequest_id and raw2.version = 1) where raw.foirequest_id = :requestid and raw.foirequestversion_id = :requestversion and raw.isactive = true ORDER BY raw.foidocumentid DESC) AS list ORDER BY created_at DESC' + sql = ''' + SELECT * FROM ( + SELECT + DISTINCT ON (foidocumentid) + raw2.created_at, raw.created_at as current_version_created_at, raw.foidocumentid, raw.filename, raw.documentpath, raw.category, raw.isactive, raw.createdby + FROM "FOIRawRequestDocuments" raw + join "FOIRawRequestDocuments" raw2 + on (raw.documentpath = raw2.documentpath) + where raw.foirequest_id = :requestid + and raw.foirequestversion_id = :requestversion + and raw.isactive = true ORDER + BY raw.foidocumentid DESC, raw2.foidocumentid asc + ) AS list ORDER BY created_at DESC + ''' + rs = db.session.execute(text(sql), {'requestid': requestid, 'requestversion': requestversion}) for row in rs: diff --git a/request-management-api/request_api/models/FOIRawRequests.py b/request-management-api/request_api/models/FOIRawRequests.py index 6c528f78c..ab9e6ee43 100644 --- a/request-management-api/request_api/models/FOIRawRequests.py +++ b/request-management-api/request_api/models/FOIRawRequests.py @@ -689,26 +689,32 @@ def getrequestssubquery(cls, filterfields, keyword, additionalfilter, userid, is @classmethod def getfilterforrequestssubquery(cls, filterfields, keyword): - keyword = keyword.lower() + _keywords = [] + if(keyword is not None): + _keywords = keyword.lower().replace(",", " ").split() #filter/search filtercondition = [] - if(keyword != 'restricted'): - for field in filterfields: - if(field == 'idNumber'): - keyword = keyword.replace('u-00', '') - - filtercondition.append(FOIRawRequest.findfield(field).ilike('%'+keyword+'%')) - if(field == 'firstName'): - filtercondition.append(FOIRawRequest.findfield('contactFirstName').ilike('%'+keyword+'%')) - if(field == 'lastName'): - filtercondition.append(FOIRawRequest.findfield('contactLastName').ilike('%'+keyword+'%')) - if(field == 'requestType'): - filtercondition.append(FOIRawRequest.findfield('requestTypeRequestType').ilike('%'+keyword+'%')) - else: - filtercondition.append(FOIRawRequest.isiaorestricted == True) + for _keyword in _keywords: + onekeywordfiltercondition = [] + if(_keyword != 'restricted'): + for field in filterfields: + if(field == 'idNumber'): + _keyword = _keyword.replace('u-00', '') + + onekeywordfiltercondition.append(FOIRawRequest.findfield(field).ilike('%'+_keyword+'%')) + if(field == 'firstName'): + onekeywordfiltercondition.append(FOIRawRequest.findfield('contactFirstName').ilike('%'+_keyword+'%')) + if(field == 'lastName'): + onekeywordfiltercondition.append(FOIRawRequest.findfield('contactLastName').ilike('%'+_keyword+'%')) + if(field == 'requestType'): + onekeywordfiltercondition.append(FOIRawRequest.findfield('requestTypeRequestType').ilike('%'+_keyword+'%')) + else: + onekeywordfiltercondition.append(FOIRawRequest.isiaorestricted == True) + + filtercondition.append(or_(*onekeywordfiltercondition)) - return or_(*filtercondition) + return and_(*filtercondition) @classmethod diff --git a/request-management-api/request_api/models/FOIRequestNotificationUsers.py b/request-management-api/request_api/models/FOIRequestNotificationUsers.py index 9e80691ca..5be9219a2 100644 --- a/request-management-api/request_api/models/FOIRequestNotificationUsers.py +++ b/request-management-api/request_api/models/FOIRequestNotificationUsers.py @@ -274,7 +274,7 @@ def getgroupfilters(cls, groups): FOIRequests.assignedgroup == group, and_( FOIRequests.assignedministrygroup == group, - 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]) + 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,StateName.onholdother.name]) ) ) ) diff --git a/request-management-api/request_api/resources/foirequest.py b/request-management-api/request_api/resources/foirequest.py index bf063df38..2cb7feadf 100644 --- a/request-management-api/request_api/resources/foirequest.py +++ b/request-management-api/request_api/resources/foirequest.py @@ -277,21 +277,6 @@ def post(ministryrequestid=None,type=None): except BusinessException as exception: return {'status': exception.status_code, 'message':exception.message}, 500 -@cors_preflight('GET,POST,OPTIONS') -@API.route('/foirequests/ministryrequestid/', defaults={'usertype':None}) -@API.route('/foirequests/ministryrequestid//') -class FOIRequestByMinistryId(Resource): - """Return request based on ministryrequestid""" - @staticmethod - @cross_origin(origins=allowedorigins()) - @auth.require - def get(ministryrequestid,usertype=None): - try : - return FOIRequest.get(requestservice().getrequestid(ministryrequestid), ministryrequestid, usertype) - except ValueError: - return {'status': 500, 'message':"Invalid Request"}, 500 - except BusinessException as exception: - return {'status': exception.status_code, 'message':exception.message}, 500 @cors_preflight('POST, DELETE, UPDATE, OPTIONS') @API.route('/foirequests//ministryrequest//section/') @@ -325,4 +310,45 @@ def post(foirequestid,foiministryrequestid,section): except KeyError as error: return {'status': False, 'message': CUSTOM_KEYERROR_MESSAGE + str(error)}, 400 except BusinessException as exception: - return {'status': exception.status_code, 'message':exception.message}, 500 \ No newline at end of file + return {'status': exception.status_code, 'message':exception.message}, 500 + + +@cors_preflight('GET,OPTIONS') +@API.route('/foirequests/ministryrequestid/', defaults={'usertype':None}) +@API.route('/foirequests/ministryrequestid//') +class FOIRequestForDocReviewer(Resource): + """Retrieve foi request for opened request - Used + in docreviewer""" + + @staticmethod + @TRACER.trace() + @cross_origin(origins=allowedorigins()) + @auth.require + def get(ministryrequestid,usertype=None): + try : + jsondata = {} + statuscode = 200 + foirequestid=requestservice().getrequestid(ministryrequestid) + if (AuthHelper.getusertype() == "iao") and (usertype is None or (usertype == "iao")): + jsondata = requestservice().getrequestdetails(foirequestid,ministryrequestid) + assignee = jsondata['assignedTo'] + isrestricted = jsondata['iaorestricteddetails']['isrestricted'] if ('isrestricted' in jsondata['iaorestricteddetails']) else False + if(canrestictdata(ministryrequestid,assignee,isrestricted,False)): + jsondata = {} + statuscode = 401 + elif usertype is not None and usertype == "ministry" and AuthHelper.getusertype() == "ministry": + jsondata = requestservice().getrequestdetailsforministry(foirequestid,ministryrequestid,AuthHelper.getministrygroups()) + assignee = jsondata['assignedministryperson'] + isrestricted = jsondata['ministryrestricteddetails']['isrestricted'] if ('isrestricted' in jsondata['ministryrestricteddetails']) else False + if(canrestictdata_ministry(ministryrequestid,assignee,isrestricted)): + jsondata = {} + statuscode = 401 + else: + statuscode = 401 + return jsondata , statuscode + except ValueError: + return {'status': 500, 'message':"Invalid Request Id"}, 500 + except KeyError as error: + return {'status': False, 'message': CUSTOM_KEYERROR_MESSAGE + str(error)}, 400 + except BusinessException as exception: + return {'status': exception.status_code, 'message':exception.message}, 500 \ No newline at end of file diff --git a/request-management-api/request_api/resources/request.py b/request-management-api/request_api/resources/request.py index 8248453e2..d90a7098d 100644 --- a/request-management-api/request_api/resources/request.py +++ b/request-management-api/request_api/resources/request.py @@ -97,7 +97,7 @@ def post(requestid=None, actiontype=None): statuslabel = requestdata['requeststatuslabel'] if int(requestid) and str(requestid) != "-1" : 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]: + if status not in [StateName.intakeinprogress.value, StateName.closed.value, StateName.redirect.value, StateName.peerreview.value, StateName.section5pending.value, StateName.appfeeowing.value, StateName.onholdother.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/schemas/foidocument.py b/request-management-api/request_api/schemas/foidocument.py index 16400d16b..a9294b124 100644 --- a/request-management-api/request_api/schemas/foidocument.py +++ b/request-management-api/request_api/schemas/foidocument.py @@ -28,7 +28,7 @@ class Meta: # pylint: disable=too-few-public-methods """Exclude unknown fields in the deserialized output.""" unknown = EXCLUDE - filename = fields.Str(data_key="filename",required=True,allow_none=False, validate=[validate.Length(max=120, error=MAX_EXCEPTION_MESSAGE)]) + filename = fields.Str(data_key="filename",required=True,allow_none=False, validate=[validate.Length(max=500, error=MAX_EXCEPTION_MESSAGE)]) documentpath = fields.Str(data_key="documentpath",required=True,allow_none=False, validate=[validate.Length(max=1000, error=MAX_EXCEPTION_MESSAGE)]) category = fields.Str(data_key="category",allow_none=True, validate=[validate.Length(max=120, error=MAX_EXCEPTION_MESSAGE)]) @@ -38,7 +38,7 @@ class Meta: # pylint: disable=too-few-public-methods """Exclude unknown fields in the deserialized output.""" unknown = EXCLUDE - filename = fields.Str(data_key="filename",required=True,allow_none=False, validate=[validate.Length(max=120, error=MAX_EXCEPTION_MESSAGE)]) + filename = fields.Str(data_key="filename",required=True,allow_none=False, validate=[validate.Length(max=500, error=MAX_EXCEPTION_MESSAGE)]) documentpath = fields.Str(data_key="documentpath",required=True,allow_none=False, validate=[validate.Length(max=1000, error=MAX_EXCEPTION_MESSAGE)]) category = fields.Str(data_key="category",allow_none=True, validate=[validate.Length(max=120, error=MAX_EXCEPTION_MESSAGE)]) diff --git a/request-management-api/request_api/services/closereasonservice.py b/request-management-api/request_api/services/closereasonservice.py index 053aca842..5b799974c 100644 --- a/request-management-api/request_api/services/closereasonservice.py +++ b/request-management-api/request_api/services/closereasonservice.py @@ -5,4 +5,9 @@ class closereasonservice: def getclosereasons(self): """ Returns the active records """ - return CloseReason.getallclosereasons() \ No newline at end of file + return CloseReason.getallclosereasons() + + @staticmethod + def getclosereason(closereasonid): + """ Returns a specific close reason by ID """ + return CloseReason.getclosereason(closereasonid) \ No newline at end of file diff --git a/request-management-api/request_api/services/commentservice.py b/request-management-api/request_api/services/commentservice.py index 29d64623e..a61e46f90 100644 --- a/request-management-api/request_api/services/commentservice.py +++ b/request-management-api/request_api/services/commentservice.py @@ -104,11 +104,11 @@ def getrawrequestcomments(self, requestid): def copyrequestcomment(self, ministryrequestid, comments, userid): _comments = [] for comment in comments: - commentresponse=FOIRequestComment.savecomment(comment['commentTypeId'], self.__copyparentcomment(ministryrequestid, comment), 1, userid,comment['dateUF']) + commentresponse=FOIRequestComment.savecomment(comment['commentTypeId'], self.__copyparentcomment(ministryrequestid, comment), 1, comment['createdby'],comment['dateUF']) _comments.append({"ministrycommentid":commentresponse.identifier,"rawcommentid":comment['commentId']}) if comment['replies']: for reply in comment['replies']: - response=FOIRequestComment.savecomment(reply['commentTypeId'], self.__copyreplycomment(ministryrequestid, reply, commentresponse.identifier), 1, userid,reply['dateUF']) + response=FOIRequestComment.savecomment(reply['commentTypeId'], self.__copyreplycomment(ministryrequestid, reply, commentresponse.identifier), 1, reply['createdby'],reply['dateUF']) _comments.append({"ministrycommentid":response.identifier,"rawcommentid":comment['commentId']}) return _comments @@ -158,6 +158,7 @@ def __comment(self, comment): "parentCommentId":comment['parentcommentid'], "commentTypeId":comment['commenttypeid'], "taggedusers" : comment['taggedusers'], + "createdby" : comment['createdby'], "edited": comment["commentsversion"] > 1 # edited: True/False } diff --git a/request-management-api/request_api/services/documentservice.py b/request-management-api/request_api/services/documentservice.py index b1e1c335d..7399abac1 100644 --- a/request-management-api/request_api/services/documentservice.py +++ b/request-management-api/request_api/services/documentservice.py @@ -110,15 +110,15 @@ def createministrydocumentversion(self, ministryrequestid, documentid, documents return FOIMinistryRequestDocument.createdocument(ministryrequestid, version, documentschema, userid) - def createrawdocumentversion(self, requestid, documentid, documentschema, userid): + def createrawdocumentversion(self, requestid, documentid, documentschema, userid): # updates existing raw request document with new attributes (i.e. name, category) version = self.__getversionforrequest(requestid, "rawrequest") document = FOIRawRequestDocument.getdocument(documentid) FOIRawRequestDocument.deActivaterawdocumentsversion(documentid, document['version'], userid) return FOIRawRequestDocument.createdocumentversion(requestid, version, self.__copydocumentproperties(document,documentschema,document['version']), userid) - def createrawrequestdocumentversion(self, requestid): + def createrawrequestdocumentversion(self, requestid): # creates new raw request document with new document id when request state changes newversion = self.__getversionforrequest(requestid,"rawrequest") - documents = self.getrequestdocuments(requestid, "rawrequest", newversion-1) + documents = FOIRawRequestDocument.getdocuments(requestid, newversion-1) documentarr = [] for document in documents: documentarr.append({"documentpath": document["documentpath"], "filename": document["filename"], "category": document['category'], "version": 1, "foirequest_id": requestid, "foirequestversion_id": newversion - 1, "createdby": document['createdby'], "created_at": document['created_at'] }) diff --git a/request-management-api/request_api/services/events/state.py b/request-management-api/request_api/services/events/state.py index d5b015d43..43a6fdd0a 100644 --- a/request-management-api/request_api/services/events/state.py +++ b/request-management-api/request_api/services/events/state.py @@ -11,6 +11,7 @@ import json from request_api.models.default_method_result import DefaultMethodResult from request_api.utils.enums import StateName +from request_api.services.closereasonservice import closereasonservice class stateevent: """ FOI Event management service @@ -63,7 +64,7 @@ def __createnotification(self, requestid, state, requesttype, userid): if state == StateName.callforrecords.value and requesttype == "ministryrequest": foirequest = notificationservice().getrequest(requestid, requesttype) _notificationtype = "Group Members" if foirequest['assignedministryperson'] is None else "State" - notification = self.__preparenotification(state) + notification = self.__preparenotification(state, requestid) if state == StateName.response.value and requesttype == "ministryrequest": signgoffapproval = FOIMinistryRequest().getrequest(requestid)['ministrysignoffapproval'] if signgoffapproval: @@ -90,8 +91,8 @@ def __createnotification(self, requestid, state, requesttype, userid): return DefaultMethodResult(True,'Notification added',requestid) return DefaultMethodResult(True,'No change',requestid) - def __preparenotification(self, state): - return self.__notificationmessage(state) + def __preparenotification(self, state, requestid): + return self.__notificationmessage(state, requestid) def __preparegroupmembernotification(self, state, requestid): if state == StateName.callforrecords.value: @@ -110,15 +111,32 @@ def __formatstate(self, 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) + comment = username + ' changed the state of the request to ' + self.__formatstate(state) + + if state == StateName.closed.value: + closereasonid = FOIMinistryRequest().getrequest(requestid).get('closereasonid') + close_reason = closereasonservice.getclosereason(closereasonid) + + if close_reason: + comment += f". The reason for the closure is {close_reason['name']}." + if state == StateName.response.value and requesttype == "ministryrequest": signgoffapproval = FOIMinistryRequest().getrequest(requestid)['ministrysignoffapproval'] if signgoffapproval: comment = comment + f". Approved by {signgoffapproval['approvername']}, {signgoffapproval['approvertitle']} on {signgoffapproval['approveddate']}" return comment - def __notificationmessage(self, state): - return 'Moved to '+self.__formatstate(state)+ ' State' + def __notificationmessage(self, state, requestid): + notification = 'Moved to ' + self.__formatstate(state) + ' State' + + if state == StateName.closed.value: + closereasonid = FOIMinistryRequest().getrequest(requestid).get('closereasonid') + close_reason = closereasonservice.getclosereason(closereasonid) + + if close_reason: + notification += f" as {close_reason['name']}." + + return notification def __notificationcfrmessage(self, requestid): metadata = FOIMinistryRequest.getmetadata(requestid) diff --git a/request-management-api/request_api/services/foirequest/requestservicegetter.py b/request-management-api/request_api/services/foirequest/requestservicegetter.py index ab4b3dfd7..2cc78f46c 100644 --- a/request-management-api/request_api/services/foirequest/requestservicegetter.py +++ b/request-management-api/request_api/services/foirequest/requestservicegetter.py @@ -119,11 +119,11 @@ def getrequestdetails(self,foirequestid, foiministryrequestid): payment = paymentservice().getpayment(foirequestid, foiministryrequestid) if approvedcfrfee is not None and approvedcfrfee != {}: requestdetails['cfrfee'] = approvedcfrfee - _totaldue = float(approvedcfrfee['feedata']['actualtotaldue']) if float(approvedcfrfee['feedata']['actualtotaldue']) > 0 else float(approvedcfrfee['feedata']['estimatedtotaldue']) + _totaldue = float(approvedcfrfee['feedata']['actualtotaldue']) if 'actualtotaldue' in approvedcfrfee['feedata'] and float(approvedcfrfee['feedata']['actualtotaldue']) > 0 else float(approvedcfrfee['feedata']['estimatedtotaldue']) _balancedue = _totaldue - (float(cfrfee['feedata']['amountpaid']) + float(approvedcfrfee['feedata']['feewaiveramount'])) requestdetails['cfrfee']['feedata']['amountpaid'] = cfrfee['feedata']['amountpaid'] requestdetails['cfrfee']['feedata']["balanceDue"] = '{:.2f}'.format(_balancedue) - if approvedcfrfee['feedata']['actualtotaldue']: + if 'actualtotaldue' in approvedcfrfee['feedata'] and approvedcfrfee['feedata']['actualtotaldue']: requestdetails['cfrfee']['feedata']["totalamountdue"] = '{:.2f}'.format(requestdetails['cfrfee']['feedata']["actualtotaldue"]) else: requestdetails['cfrfee']['feedata']["totalamountdue"] = '{:.2f}'.format(requestdetails['cfrfee']['feedata']["estimatedtotaldue"]) @@ -268,7 +268,7 @@ def getonholdtransition(self, foiministryrequestid): onholddate = None transitions = FOIMinistryRequest.getrequeststatusById(foiministryrequestid) for entry in transitions: - if entry['requeststatuslabel'] == StateName.onhold.name: + if (entry['requeststatuslabel'] == StateName.onhold.name or entry['requeststatuslabel'] == StateName.onholdother.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/requestservice.py b/request-management-api/request_api/services/requestservice.py index 2bc99921a..3c600a006 100644 --- a/request-management-api/request_api/services/requestservice.py +++ b/request-management-api/request_api/services/requestservice.py @@ -119,7 +119,7 @@ def postpaymentstatetransition( ) def updateduedate( - self, requestid, ministryrequestid, offholddate, foirequestschema, nextstatename + self, requestid, ministryrequestid, offholddate, foirequestschema, nextstatename ): foirequest = self.getrequest(requestid, ministryrequestid) currentstatus = ( @@ -131,8 +131,9 @@ def updateduedate( # Check for Off Hold if ( currentstatus not in (None, "") - and currentstatus == StateName.onhold.value - and nextstatename != StateName.response.value + and ((currentstatus == StateName.onhold.value + and nextstatename != StateName.response.value) + or currentstatus == StateName.onholdother.value) ): skipcalculation = self.__skipduedatecalculation( ministryrequestid, offholddate, currentstatus, nextstatename @@ -268,12 +269,12 @@ def calculateduedate(self, ministryrequestid, foirequest, paymentdate): def __skipduedatecalculation(self, ministryrequestid, offholddate, currentstatus="", nextstatename=""): - previousoffholddate = FOIMinistryRequest.getlastoffholddate(ministryrequestid) + previousoffholddate = FOIMinistryRequest.getlastoffholddate(ministryrequestid, currentstatus) if ( - currentstatus not in (None, "") + (currentstatus not in (None, "") and currentstatus == StateName.onhold.value and nextstatename not in (None, "") - and currentstatus == nextstatename + and currentstatus == nextstatename) ): return True if previousoffholddate not in (None, ""): diff --git a/request-management-api/request_api/utils/enums.py b/request-management-api/request_api/utils/enums.py index 356b347e1..b468ad49f 100644 --- a/request-management-api/request_api/utils/enums.py +++ b/request-management-api/request_api/utils/enums.py @@ -36,6 +36,7 @@ class MinistryTeamWithKeycloackGroup(Enum): AG = "AG Ministry Team" BRD = "BRD Ministry Team" CAS = "CAS Ministry Team" + CAF = "CAF Ministry Team" CITZ = "CITZ Ministry Team" CLB = "CLB Ministry Team" DAS = "DAS Ministry Team" @@ -73,7 +74,8 @@ class MinistryTeamWithKeycloackGroup(Enum): ECC = "ECC Ministry Team" JED = "JED Ministry Team" COR = "COR Ministry Team" - HSG = "HSG Ministry Team" + HSG = "HSG Ministry Team", + LSB = "LSB Ministry Team" @staticmethod def list(): @@ -164,6 +166,7 @@ class StateName(Enum): readytoscan = "Ready to Scan" appfeeowing = "App Fee Owing" section5pending = "Section 5 Pending" + onholdother = "On Hold - Other" class CacheUrls(Enum): keycloakusers= "/api/foiassignees" programareas= "/api/foiflow/programareas"