diff --git a/forms-flow-web/src/components/FOI/Dashboard/IAO/AdvancedSearch/SearchComponent.js b/forms-flow-web/src/components/FOI/Dashboard/IAO/AdvancedSearch/SearchComponent.js
index 78af5d3c9..dc3233ca6 100644
--- a/forms-flow-web/src/components/FOI/Dashboard/IAO/AdvancedSearch/SearchComponent.js
+++ b/forms-flow-web/src/components/FOI/Dashboard/IAO/AdvancedSearch/SearchComponent.js
@@ -143,7 +143,8 @@ const AdvancedSearch = ({ userDetail }) => {
[StateEnum.review.label]: false,
[StateEnum.signoff.label]: false,
[StateEnum.closed.label]: false,
- [StateEnum.callforrecordsoverdue.label]: false
+ [StateEnum.callforrecordsoverdue.label]: false,
+ [StateEnum.onholdother.label]: false
};
const [requestState, setRequestState] = useState(() => {
diff --git a/forms-flow-web/src/components/FOI/Dashboard/Ministry/AdvancedSearch/SearchComponent.js b/forms-flow-web/src/components/FOI/Dashboard/Ministry/AdvancedSearch/SearchComponent.js
index 5058944d6..93eacfa3d 100644
--- a/forms-flow-web/src/components/FOI/Dashboard/Ministry/AdvancedSearch/SearchComponent.js
+++ b/forms-flow-web/src/components/FOI/Dashboard/Ministry/AdvancedSearch/SearchComponent.js
@@ -131,7 +131,8 @@ const AdvancedSearch = ({ userDetail }) => {
[StateEnum.review.label]: false,
[StateEnum.signoff.label]: false,
[StateEnum.closed.label]: false,
- [StateEnum.callforrecordsoverdue.label]: false
+ [StateEnum.callforrecordsoverdue.label]: false,
+ [StateEnum.onholdother.label]: false
};
const [requestState, setRequestState] = useState(() => {
if (Object.keys(advancedSearchParams).length > 0 && advancedSearchParams.requestState.length > 0) {
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 23450bed3..61839a970 100644
--- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js
+++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js
@@ -373,6 +373,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
);
}
@@ -893,7 +894,6 @@ const FOIRequest = React.memo(({ userDetail, openApplicantProfileModal }) => {
const handleSaveRequest = (_state, _unSaved, id) => {
setHeader(_state);
-
if (!_unSaved) {
setUnSavedRequest(_unSaved);
dispatch(fetchFOIRequestDetailsWrapper(id || requestId, ministryId));
diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js
index 2a76a6055..b0ed964ba 100644
--- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js
+++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequestHeader/index.js
@@ -226,6 +226,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 4ee9e5deb..c171c02c9 100644
--- a/forms-flow-web/src/components/FOI/FOIRequest/RequestDetails.js
+++ b/forms-flow-web/src/components/FOI/FOIRequest/RequestDetails.js
@@ -266,8 +266,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";
}
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 bb67e4ce7..3bacb9768 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/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..7cb10eef7 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,10 @@ 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 change Request #{_requestNumber} to {StateEnum.onholdother.name}? This should be used for scenarios
+ that are not fee related (such as Third Party notice). This will stop the clock.>};
default:
return {title: "", body: ""};
}
diff --git a/forms-flow-web/src/components/FOI/customComponents/Records/util.js b/forms-flow-web/src/components/FOI/customComponents/Records/util.js
index 44b2d1a33..e47225424 100644
--- a/forms-flow-web/src/components/FOI/customComponents/Records/util.js
+++ b/forms-flow-web/src/components/FOI/customComponents/Records/util.js
@@ -151,12 +151,7 @@ export const sortDivisionalFiles = (divisionMap) => {
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 632bf69fd..b05df147e 100644
--- a/forms-flow-web/src/components/FOI/customComponents/StateDropDown.js
+++ b/forms-flow-web/src/components/FOI/customComponents/StateDropDown.js
@@ -111,7 +111,15 @@ const StateDropDown = ({
const appendRecordsReadyForReview = (stateList) => {
const recordsreadyforreview = { status: "Records Ready for Review", isSelected: false };
let appendedList = stateList.slice();
- appendedList.splice(-1, 0, recordsreadyforreview);
+ if(previousState === StateEnum.open.name || previousState === StateEnum.response.name)
+ appendedList.splice(-2, 0, recordsreadyforreview);
+ else 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"))
@@ -225,7 +233,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/statusEnum.js b/forms-flow-web/src/constants/FOI/statusEnum.js
index 8b15ca80a..e9624e96a 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,18 +137,21 @@ 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 },
@@ -157,8 +173,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 +226,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 +253,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/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 01bfb9017..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):
diff --git a/notification-manager/notification_api/io/message/schemas/notification.py b/notification-manager/notification_api/io/message/schemas/notification.py
index 87b82a0b7..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):
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/83cfc8047acf_.py b/request-management-api/migrations/versions/83cfc8047acf_.py
new file mode 100644
index 000000000..ee65fd455
--- /dev/null
+++ b/request-management-api/migrations/versions/83cfc8047acf_.py
@@ -0,0 +1,41 @@
+"""empty message
+
+Revision ID: 83cfc8047acf
+Revises: 77ef102e9823
+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 = '77ef102e9823'
+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/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 2dc5b65e4..f49f53c14 100644
--- a/request-management-api/request_api/models/FOIMinistryRequestDocuments.py
+++ b/request-management-api/request_api/models/FOIMinistryRequestDocuments.py
@@ -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 d1f0b86b8..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
@@ -491,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')
@@ -846,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,
@@ -894,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"]})
@@ -920,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:
@@ -1113,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')
@@ -1328,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))
@@ -1413,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 182cfcc69..7d75b4140 100644
--- a/request-management-api/request_api/models/FOIRawRequestDocuments.py
+++ b/request-management-api/request_api/models/FOIRawRequestDocuments.py
@@ -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/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/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/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/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 b2dec36cc..2cc78f46c 100644
--- a/request-management-api/request_api/services/foirequest/requestservicegetter.py
+++ b/request-management-api/request_api/services/foirequest/requestservicegetter.py
@@ -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..8626742e8 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,10 @@ 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
+ and nextstatename != StateName.open.value))
):
skipcalculation = self.__skipduedatecalculation(
ministryrequestid, offholddate, currentstatus, nextstatename
@@ -268,12 +270,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, "")
- and currentstatus == StateName.onhold.value
+ (currentstatus not in (None, "")
+ and (currentstatus == StateName.onhold.value or currentstatus == StateName.onholdother.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 e174ad3ba..8a87ab502 100644
--- a/request-management-api/request_api/utils/enums.py
+++ b/request-management-api/request_api/utils/enums.py
@@ -170,6 +170,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"