diff --git a/forms-flow-web/src/components/FOI/Dashboard/IAO/AdvancedSearch/DataGridAdvancedSearch.js b/forms-flow-web/src/components/FOI/Dashboard/IAO/AdvancedSearch/DataGridAdvancedSearch.js index 8cd13422e..c5b84c935 100644 --- a/forms-flow-web/src/components/FOI/Dashboard/IAO/AdvancedSearch/DataGridAdvancedSearch.js +++ b/forms-flow-web/src/components/FOI/Dashboard/IAO/AdvancedSearch/DataGridAdvancedSearch.js @@ -12,7 +12,8 @@ import { getReceivedDate, // onBehalfFullName, getRecordsDue, - LightTooltip, + LightTooltip, + displayQueueFlagIcons, } from "../../utils"; import { ActionContext } from "./ActionContext"; import { @@ -97,6 +98,12 @@ const DataGridAdvancedSearch = ({ userDetail }) => { const ProcessingTeamColumns = [ + { + field: "flags", + headerName: "FLAGS", + headerAlign: "left", + renderCell: displayQueueFlagIcons, + }, { field: "axisRequestId", headerName: "ID NUMBER", @@ -189,6 +196,12 @@ const DataGridAdvancedSearch = ({ userDetail }) => { ]; const IntakeTeamColumns = [ + { + field: "flags", + headerName: "FLAGS", + headerAlign: "left", + renderCell: displayQueueFlagIcons, + }, { field: "applicantName", headerName: "APPLICANT NAME", @@ -250,6 +263,12 @@ const DataGridAdvancedSearch = ({ userDetail }) => { ]; const FlexTeamColumns = [ + { + field: "flags", + headerName: "FLAGS", + headerAlign: "left", + renderCell: displayQueueFlagIcons, + }, { field: "axisRequestId", headerName: "ID NUMBER", diff --git a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js index feb5e61ee..2deb1f15f 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/FOIRequest.js @@ -796,7 +796,7 @@ const FOIRequest = React.memo(({ userDetail }) => { _status, requestExtensions, }); - + setRequestStatus(mappedBottomText); }; @@ -1045,7 +1045,8 @@ const FOIRequest = React.memo(({ userDetail }) => {
- {bottomTextArray.length > 0 && + {isOIPCReview && requestDetails.isreopened ? "" + : bottomTextArray.length > 0 && _requestStatus && _requestStatus.toLowerCase().includes("days") && bottomTextArray.map((text) => { diff --git a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx index a9f772b0e..818845a9f 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx +++ b/forms-flow-web/src/components/FOI/FOIRequest/OIPCDetails/OIPCItem.jsx @@ -183,7 +183,7 @@ const OIPCItem = (props) => { InputLabelProps={{ shrink: true }} InputProps={{inputProps: { max: formatDate(new Date())} }} type="date" - error={(!oipc.outcomeid || oipc.outcomeid === 5) && oipc.receiveddate === null} + error={(!oipc.outcomeid || oipc.outcomeid === 5) && oipc.receiveddate === null || oipc.receiveddate === ""} required disabled={oipc.outcomeid && oipc.outcomeid !== 5} /> @@ -360,15 +360,15 @@ const OIPCItem = (props) => { handleInquiryFields(event.target.value, "COMPLYDATE")} InputLabelProps={{ shrink: true }} InputProps={{inputProps: { min: oipc.receiveddate ? formatDate(new Date(oipc.receiveddate)) : null } }} type="date" - error={(!oipc.outcomeid || oipc.outcomeid === 5) && oipc.inquiryattributes.inquirydate === null} - required + error={oipc.inquiryattributes.orderno ? (!oipc.outcomeid || oipc.outcomeid === 5) && oipc.inquiryattributes.inquirydate === null || oipc.inquiryattributes.inquirydate === "" : false} + required={oipc.inquiryattributes.orderno} disabled={oipc.outcomeid && oipc.outcomeid !== 5} /> @@ -380,8 +380,8 @@ const OIPCItem = (props) => { value={oipc.inquiryattributes.orderno} onChange = {(event) => handleInquiryFields(event.target.value, "ORDERNO")} InputLabelProps={{ shrink: true }} - error={(!oipc.outcomeid || oipc.outcomeid === 5) && oipc.inquiryattributes.orderno === ""} - required + error={oipc.inquiryattributes.inquirydate ? (!oipc.outcomeid || oipc.outcomeid === 5) && oipc.inquiryattributes.orderno === "" : false} + required={oipc.inquiryattributes.inquirydate} disabled={oipc.outcomeid && oipc.outcomeid !== 5} placeholder="Order Number" /> @@ -394,9 +394,7 @@ const OIPCItem = (props) => { onChange = {(event) => handleInquiryFields(event.target.value, "INQUIRYOUTCOME")} fullWidth value={oipc.inquiryattributes.inquiryoutcome ? oipc.inquiryattributes.inquiryoutcome : -1} - label="Outcome" - error={(!oipc.outcomeid || oipc.outcomeid === 5) && oipc.inquiryattributes.inquiryoutcome === null} - required + label="Inquiry Outcome" disabled={oipc.outcomeid && oipc.outcomeid !== 5} > diff --git a/forms-flow-web/src/components/FOI/FOIRequest/utils.js b/forms-flow-web/src/components/FOI/FOIRequest/utils.js index 2905bfea2..dc5c8abeb 100644 --- a/forms-flow-web/src/components/FOI/FOIRequest/utils.js +++ b/forms-flow-web/src/components/FOI/FOIRequest/utils.js @@ -349,8 +349,13 @@ export const checkValidationError = ( !requiredRequestDetailsValues.requestStartDate || !requiredAxisDetails.axisRequestId || (oipcData?.length > 0 && isOipcReview && oipcData?.some((oipc) => { - return oipc.oipcno === "" || oipc.receiveddate === null || oipc.receiveddate === "" || oipc.reviewtypeid === null || oipc.reasonid === null || oipc.statusid === null || - oipc.inquiryattributes?.orderno === "" || oipc.inquiryattributes?.inquiryoutcome === null || oipc.inquiryattributes?.inquirydate === null || oipc.inquiryattributes?.inquirydate === ""; + if (oipc.inquiryattributes?.inquirydate) { + return oipc.inquiryattributes.orderno === ""; + } + if (oipc.inquiryattributes?.orderno) { + return oipc.inquiryattributes?.inquirydate === null || oipc.inquiryattributes?.inquirydate === ""; + } + return oipc.oipcno === "" || oipc.receiveddate === null || oipc.receiveddate === "" || oipc.reviewtypeid === null || oipc.reasonid === null || oipc.statusid === null; })) ); }; diff --git a/request-management-api/migrations/versions/3e91d4f34699_oipc_notifications.py b/request-management-api/migrations/versions/3e91d4f34699_oipc_notifications.py new file mode 100644 index 000000000..76141c027 --- /dev/null +++ b/request-management-api/migrations/versions/3e91d4f34699_oipc_notifications.py @@ -0,0 +1,32 @@ +"""empty message + +Revision ID: 3e91d4f34699 +Revises: 455a24da8c58 +Create Date: 2023-11-30 00:11:56.160830 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = '3e91d4f34699' +down_revision = '455a24da8c58' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.execute('Insert into public."NotificationTypes" (name, description, isactive) values (\'OIPC\', \'OIPC\', true);commit;') + op.execute('Insert into public."NotificationTypes" (name, description, isactive) values (\'OIPC Due Reminder\', \'OIPC Due Reminder\', true);commit;') + op.execute('Insert into public."CommentTypes" (name, description, isactive) values (\'OIPC Tracking\', \'OIPC Tracking\', true);commit;') + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.execute('delete from public."NotificationTypes" where name in (\'OIPC\');commit;') + op.execute('delete from public."NotificationTypes" where name in (\'OIPC Due Reminder\');commit;') + op.execute('delete from public."CommentTypes" where name in (\'OIPC Tracking\');commit;') + # ### end Alembic commands ### diff --git a/request-management-api/request_api/models/FOIMinistryRequests.py b/request-management-api/request_api/models/FOIMinistryRequests.py index 8abc19dc7..cb601bd7f 100644 --- a/request-management-api/request_api/models/FOIMinistryRequests.py +++ b/request-management-api/request_api/models/FOIMinistryRequests.py @@ -562,7 +562,7 @@ def getrequestssubquery(cls, groups, filterfields, keyword, additionalfilter, us SubjectCode, SubjectCode.subjectcodeid == FOIMinistryRequestSubjectCode.subjectcodeid, isouter=True - ).filter(FOIMinistryRequest.requeststatusid != 3) + ).filter(or_(FOIMinistryRequest.requeststatusid != 3, and_(FOIMinistryRequest.isoipcreview == True, FOIMinistryRequest.requeststatusid == 3))) if(additionalfilter == 'watchingRequests'): #watchby @@ -788,6 +788,33 @@ def getupcomingdivisionduerecords(cls): finally: db.session.close() return upcomingduerecords + + @classmethod + def getupcomingoipcduerecords(cls): + upcomingduerecords = [] + try: + sql = """select axisrequestid, filenumber, fma.foiministryrequestid , fma.foiministryrequestversion, fma.foirequest_id, + frd.oipcid , frd.inquiryattributes ->> 'orderno'as orderno, + frd.inquiryattributes ->> 'inquirydate' as duedate, frd.created_at, frd.createdby + from "FOIRequestOIPC" frd + inner join (select distinct on (fpa.foiministryrequestid) foiministryrequestid, version as foiministryrequestversion, axisrequestid, filenumber, foirequest_id, requeststatusid + from "FOIMinistryRequests" fpa + order by fpa.foiministryrequestid , fpa.version desc) fma on frd.foiministryrequest_id = fma.foiministryrequestid + and frd.foiministryrequestversion_id = fma.foiministryrequestversion and fma.requeststatusid not in (5,6,4,11,3,15) + and (frd.inquiryattributes ->> 'inquirydate')::date between NOW() - INTERVAL '7 DAY' AND NOW() + INTERVAL '7 DAY' + order by frd.foiministryrequest_id , frd.foiministryrequestversion_id desc;""" + rs = db.session.execute(text(sql)) + for row in rs: + upcomingduerecords.append({"axisrequestid": row["axisrequestid"], "filenumber": row["filenumber"], + "foiministryrequestid": row["foiministryrequestid"], "version": row["foiministryrequestversion"], + "foirequest_id": row["foirequest_id"], "created_at": row["created_at"], "createdby": row["createdby"], + "orderno": row["orderno"],"duedate": row["duedate"]}) + except Exception as ex: + logging.error(ex) + raise ex + finally: + db.session.close() + return upcomingduerecords @classmethod def updateduedate(cls, ministryrequestid, duedate, userid)->DefaultMethodResult: diff --git a/request-management-api/request_api/models/OIPCReviewTypesReasons.py b/request-management-api/request_api/models/OIPCReviewTypesReasons.py index 3fc17e221..32fe9334b 100644 --- a/request-management-api/request_api/models/OIPCReviewTypesReasons.py +++ b/request-management-api/request_api/models/OIPCReviewTypesReasons.py @@ -7,10 +7,10 @@ class OIPCReviewTypesReasons(db.Model): __tablename__ = 'OIPCReviewTypesReasons' # Defining the columns reviewtypereasonid = db.Column(db.Integer, primary_key=True,autoincrement=True) - reviewtypeid = db.Column(db.Integer, ForeignKey('FOIReviewTypes')) - relationship("FOIReviewTypes", backref=backref("FOIReviewTypes"), uselist=False) - reasonid = db.Column(db.Integer, ForeignKey('FOIReasons')) - relationship("FOIReasons", backref=backref("FOIReasons"), uselist=False) + reviewtypeid = db.Column(db.Integer, ForeignKey('OIPCReviewTypes')) + relationship("OIPCReviewTypes", backref=backref("OIPCReviewTypes"), uselist=False) + reasonid = db.Column(db.Integer, ForeignKey('OIPCReasons')) + relationship("OIPCReasons", backref=backref("OIPCReasons"), uselist=False) isactive = db.Column(db.Boolean, unique=False, nullable=False) @classmethod diff --git a/request-management-api/request_api/services/commons/duecalculator.py b/request-management-api/request_api/services/commons/duecalculator.py index d787bda94..c6ecd061e 100644 --- a/request-management-api/request_api/services/commons/duecalculator.py +++ b/request-management-api/request_api/services/commons/duecalculator.py @@ -20,7 +20,13 @@ def getpreviousbusinessday(self, cfrduedate,ca_holidays): return _prevbusinessday else: return self.getpreviousbusinessday(_prevbusinessday,ca_holidays) - + + def getpreviousbusinessday_by_n(self, duedate, ca_holidays, n): + _prevbusinessday = duedate + for i in range(n): + _prevbusinessday = self.getpreviousbusinessday(_prevbusinessday, ca_holidays) + return _prevbusinessday + def formatduedate(self,input): return datetimehandler().formatdate(input) diff --git a/request-management-api/request_api/services/events/oipc.py b/request-management-api/request_api/services/events/oipc.py new file mode 100644 index 000000000..1742ca1b2 --- /dev/null +++ b/request-management-api/request_api/services/events/oipc.py @@ -0,0 +1,156 @@ + +from os import stat +from re import VERBOSE +from request_api.models.FOIRequestOIPC import FOIRequestOIPC +from request_api.services.commentservice import commentservice +from request_api.services.oipcservice import oipcservice +from request_api.services.notificationservice import notificationservice +from request_api.models.FOIMinistryRequests import FOIMinistryRequest +import json +from request_api.models.default_method_result import DefaultMethodResult +from enum import Enum +from request_api.exceptions import BusinessException +from dateutil.parser import parse +from request_api.utils.enums import CommentType + +class oipcevent: + """ FOI OIPC Event management service + """ + + def createoipcevent(self, requestid, userid): + inquiryoutcomes = oipcservice().getinquiryoutcomes() + version = FOIMinistryRequest.getversionforrequest(requestid) + curoipcs = FOIRequestOIPC.getoipc(requestid, version) + prevoipcs = FOIRequestOIPC.getoipc(requestid, version[0]-1) + oipcsummary = self.__maintained(curoipcs, prevoipcs, inquiryoutcomes) + if oipcsummary is None or (oipcsummary and len(oipcsummary) <1): + return DefaultMethodResult(True,'No change',requestid) + try: + for oipc in oipcsummary: + self.__createcomment(requestid, oipc, userid) + self.__createnotification(requestid, oipc, userid) + return DefaultMethodResult(True,'Comment posted',requestid) + except BusinessException as exception: + return DefaultMethodResult(False,'unable to post comment - '+exception.message,requestid) + + + def __createcomment(self, requestid, oipc, userid): + comment = {"ministryrequestid": requestid, "comment": self.__preparemessage(oipc)} + commentservice().createministryrequestcomment(comment, userid, CommentType.OIPC.value) + + def __createnotification(self, requestid, oipc, userid): + return notificationservice().createnotification({"message" : self.__preparemessage(oipc)}, requestid, "ministryrequest", "OIPC", userid, False) + + + def __maintained(self,coipcs, poipcs, inquiryoutcomes): + oipcs = [] + for coipc in coipcs: + if self.__isoipcpresent(self.__getoipcnumber(coipc), poipcs) == False: + oipcs.append(self.__createoipcsummary(coipc, EventType.add.value, inquiryoutcomes)) + else: + if self.__isoutcomeclosed(coipc, poipcs) == True: + oipcs.append(self.__createoipcsummary(coipc, EventType.close.value, inquiryoutcomes)) + if self.__isinquirychanged(coipc, poipcs) == True: + oipcs.append(self.__createoipcsummary(coipc, EventType.inquirychange.value, inquiryoutcomes)) + elif self.__isinquiryoutcomechanged(coipc, poipcs, inquiryoutcomes) == True: + oipcs.append(self.__createoipcsummary(coipc, EventType.inquiryoutcome.value, inquiryoutcomes)) + return oipcs + + # def __deleted(self, coipcs, poipcs): + # oipcs = [] + # for poipc in poipcs: + # if self.__isoipcpresent(self.__getoipcnumber(poipc), coipcs) == False: + # oipcs.append(self.__createoipcsummary(poipc, EventType.delete.value)) + # return oipcs + + def __isoipcpresent(self, oipcno, poipcs): + for oipc in poipcs: + if self.__getoipcnumber(oipc) == oipcno: + return True + return False + + def __isoutcomeclosed(self, coipc, poipcs): + for oipc in poipcs: + if self.__getoipcnumber(oipc) == self.__getoipcnumber(coipc) and self.__getoutcome(oipc) != self.__getoutcome(coipc) and self.__getoutcome(coipc) == "Closed": + return True + return False + + def __isinquirychanged(self, coipc, poipcs): + for oipc in poipcs: + if self.__getoipcnumber(oipc) == self.__getoipcnumber(coipc) and self.__getinquiry(oipc) != self.__getinquiry(coipc): + if self.__getinquirycomplydate(coipc) not in (None, "") and self.__getinquiryorderno(coipc) not in (None, "") and (self.__getinquiryorderno(oipc) != self.__getinquiryorderno(coipc) or self.__getinquirycomplydate(oipc) != self.__getinquirycomplydate(coipc)): + return True + return False + + def __isinquiryoutcomechanged(self, coipc, poipcs, inquiryoutcomes): + for oipc in poipcs: + if self.__getoipcnumber(oipc) == self.__getoipcnumber(coipc) and self.__getinquiry(oipc) != self.__getinquiry(coipc): + if self.__getinquiryoutcome(coipc, inquiryoutcomes) not in (None, "") and self.__getinquiryoutcome(oipc, inquiryoutcomes) != self.__getinquiryoutcome(coipc, inquiryoutcomes): + return True + return False + + def __createoipcsummary(self, oipc, event, inquiryoutcomes): + return {'oipcno': self.__getoipcnumber(oipc), + 'reviewtype': self.__getoipcreviewtype(oipc), + 'reason':self.__getreason(oipc), + 'outcome': self.__getoutcome(oipc), + 'inquirycomplydate': self.__getinquirycomplydate(oipc), + 'inquiryorderno': self.__getinquirycomplydate(oipc), + 'inquiryoutcome': self.__getinquiryoutcome(oipc, inquiryoutcomes), + 'event': event} + + def __getoipcnumber(self, dataschema): + return dataschema['oipcno'] + + def __getoipcreviewtype(self, dataschema): + return dataschema['reviewtype.name'] + + def __getreason(self, dataschema): + return dataschema['reason.name'] + + def __getoutcome(self, dataschema): + return dataschema['outcome.name'] if dataschema['outcomeid'] not in (None,"") else None + + def __getinquirycomplydate(self, dataschema): + return self.__getinquiry(dataschema)['inquirydate'] if dataschema['inquiryattributes'] not in (None,"") else None + + def __getinquiryoutcome(self, dataschema, inquiryoutcomes): + if dataschema['inquiryattributes'] not in (None,""): + inquiryoutcomeid = self.__getinquiry(dataschema)['inquiryoutcome'] + if inquiryoutcomeid not in (None,""): + return self.__getinquiryoutcomename(inquiryoutcomeid, inquiryoutcomes) + return None + + def __getinquiryorderno(self, dataschema): + return self.__getinquiry(dataschema)['orderno'] if dataschema['inquiryattributes'] not in (None,"") else None + + def __getinquiry(self, dataschema): + return dataschema['inquiryattributes'] + + def __getinquiryoutcomename(self, inquiryoutcomeid, inquiryoutcomes): + for outcome in inquiryoutcomes: + if inquiryoutcomeid == outcome["inquiryoutcomeid"]: + return outcome["name"] + return None + + def __preparemessage(self, oipc): + if oipc['event'] == EventType.add.value: + return 'OIPC '+ oipc['reviewtype'] +' opened for '+ oipc['reason'] + elif oipc['event'] == EventType.close.value: + return 'OIPC '+ oipc['reviewtype'] +' closed for '+ oipc['reason'] + elif oipc['event'] == EventType.inquirychange.value: + _inquirychange_msg = 'OIPC Inquiry Order '+ oipc['inquiryorderno'] +' compliance date due '+oipc['inquirycomplydate'] + if oipc['inquiryoutcome'] not in (None, ""): + return _inquirychange_msg+' .Inquiry Decision:' + oipc['inquiryoutcome'] + else: + return _inquirychange_msg + elif oipc['event'] == EventType.inquiryoutcome.value: + return 'OIPC '+ oipc['reviewtype'] +' Inquiry Decision: '+ oipc['inquiryoutcome'] + + +class EventType(Enum): + add = "add" + delete = "delete" + close = "close" + inquirychange = "inquirychange" + inquiryoutcome = "inquiryoutcome" diff --git a/request-management-api/request_api/services/events/oipcduedate.py b/request-management-api/request_api/services/events/oipcduedate.py new file mode 100644 index 000000000..88fbd51b2 --- /dev/null +++ b/request-management-api/request_api/services/events/oipcduedate.py @@ -0,0 +1,69 @@ + +from os import stat +from re import VERBOSE +from request_api.services.commentservice import commentservice +from request_api.services.commons.duecalculator import duecalculator +from request_api.services.notificationservice import notificationservice +from request_api.models.FOIMinistryRequests import FOIMinistryRequest +import json +from request_api.models.default_method_result import DefaultMethodResult +from request_api.exceptions import BusinessException +from dateutil.parser import parse +from flask import current_app + +class oipcduedateevent(duecalculator): + """ FOI OIPC Due Date Event management service + """ + + def createdueevent(self): + try: + _today = self.gettoday() + notificationservice().dismissremindernotification("ministryrequest", self.__notificationtype()) + ca_holidays = self.getholidays() + _upcomingdues = FOIMinistryRequest.getupcomingoipcduerecords() + for entry in _upcomingdues: + _duedate = self.formatduedate(entry['duedate']) + message = None + if _duedate == _today: + message = self.__todayduemessage(entry) + elif self.getpreviousbusinessday(entry['duedate'],ca_holidays) == _today: + message = self.__upcomingduemessage(entry) + elif self.getpreviousbusinessday_by_n(entry['duedate'],ca_holidays, 2) == _today: + message = self.__upcomingduemessage(entry) + self.__createnotification(message,entry['foiministryrequestid']) + self.__createcomment(entry, message) + return DefaultMethodResult(True,'OIPC reminder notifications created',_today) + except BusinessException as exception: + current_app.logger.error("%s,%s" % ('OIPC reminder Notification Error', exception.message)) + return DefaultMethodResult(False,'OIPC reminder notifications failed',_today) + + def __createnotification(self, message, requestid): + if message is not None: + return notificationservice().createnotification({"message" : message}, requestid, "ministryrequest", self.__notificationtype(), self.__defaultuserid(), False) + + def __createcomment(self, entry, message): + if message is not None: + _comment = self.__preparecomment(entry, message) + return commentservice().createcomments(_comment, self.__defaultuserid(), 2) + + + def __preparecomment(self, foirequest, message): + _comment = dict() + _comment['comment'] = message + _comment['ministryrequestid'] = foirequest["foiministryrequestid"] + _comment['version'] = foirequest["version"] + _comment['taggedusers'] = None + _comment['parentcommentid'] = None + return _comment + + def __upcomingduemessage(self, data): + return 'OIPC Inquiry Order '+data['orderno'] +' compliance date due on ' + parse(str(data['duedate'])).strftime("%Y %b %d").upper() + + def __todayduemessage(self, data): + return 'OIPC Inquiry Order '+data['orderno'] +' compliance due Today' + + def __notificationtype(self): + return "OIPC Due Reminder" + + def __defaultuserid(self): + return "System" \ No newline at end of file diff --git a/request-management-api/request_api/services/eventservice.py b/request-management-api/request_api/services/eventservice.py index 9610cb5a6..5e5da210d 100644 --- a/request-management-api/request_api/services/eventservice.py +++ b/request-management-api/request_api/services/eventservice.py @@ -3,12 +3,14 @@ from re import VERBOSE from request_api.services.events.state import stateevent from request_api.services.events.division import divisionevent +from request_api.services.events.oipc import oipcevent from request_api.services.events.assignment import assignmentevent from request_api.services.events.cfrdate import cfrdateevent from request_api.services.events.comment import commentevent from request_api.services.events.watcher import watcherevent from request_api.services.events.legislativedate import legislativedateevent from request_api.services.events.divisiondate import divisiondateevent +from request_api.services.events.oipcduedate import oipcduedateevent from request_api.services.events.extension import extensionevent from request_api.services.events.cfrfeeform import cfrfeeformevent from request_api.services.events.payment import paymentevent @@ -33,8 +35,9 @@ def posteventsync(self, requestid, requesttype, userid, username, isministryuser stateeventresponse = stateevent().createstatetransitionevent(requestid, requesttype, userid, username) divisioneventresponse = divisionevent().createdivisionevent(requestid, requesttype, userid) assignmentresponse = assignmentevent().createassignmentevent(requestid, requesttype, userid, isministryuser,assigneename,username) - if stateeventresponse.success == False or divisioneventresponse.success == False or assignmentresponse.success == False: - current_app.logger.error("FOI Notification failed for event for request= %s ; state response=%s ; division response=%s ; assignment response=%s" % (requestid, stateeventresponse.message, divisioneventresponse.message, assignmentresponse.message)) + oipcresponse = oipcevent().createoipcevent(requestid, userid) + if stateeventresponse.success == False or divisioneventresponse.success == False or assignmentresponse.success == False or oipcresponse.success == False: + current_app.logger.error("FOI Notification failed for event for request= %s ; state response=%s ; division response=%s ; assignment response=%s ; oipc response=%s" % (requestid, stateeventresponse.message, divisioneventresponse.message, assignmentresponse.message, oipcresponse.message)) except BusinessException as exception: self.__logbusinessexception(exception) @@ -60,10 +63,11 @@ def postreminderevent(self): cfreventresponse = cfrdateevent().createdueevent() legislativeeventresponse = legislativedateevent().createdueevent() divisioneventresponse = divisiondateevent().createdueevent() + oipceventresponse = oipcduedateevent().createdueevent() paymentremindereventresponse = paymentevent().createpaymentreminderevent() - section5pendingresponse = section5pendingevent().createdueevent() - if cfreventresponse.success == False or legislativeeventresponse.success == False or divisioneventresponse.success == False or paymentremindereventresponse.success == False or section5pendingresponse == False: - current_app.logger.error("FOI Notification failed for reminder event response=%s ; legislative response=%s ; division response=%s ; payment response=%s ; section5pending response=%s" % (cfreventresponse.message, legislativeeventresponse.message, divisioneventresponse.message, paymentremindereventresponse.message, section5pendingresponse.message)) + section5pendingresponse = section5pendingevent().createdueevent() + if cfreventresponse.success == False or legislativeeventresponse.success == False or divisioneventresponse.success == False or paymentremindereventresponse.success == False or section5pendingresponse == False or oipceventresponse == False: + current_app.logger.error("FOI Notification failed for reminder event response=%s ; legislative response=%s ; division response=%s ; payment response=%s ; section5pending response=%s ; oipcduereminder response=%s" % (cfreventresponse.message, legislativeeventresponse.message, divisioneventresponse.message, paymentremindereventresponse.message, section5pendingresponse.message, oipceventresponse.message)) return DefaultMethodResult(False,'Due reminder notifications failed',cfreventresponse.identifier) return DefaultMethodResult(True,'Due reminder notifications created',cfreventresponse.identifier) except BusinessException as exception: diff --git a/request-management-api/request_api/services/foirequest/requestservicegetter.py b/request-management-api/request_api/services/foirequest/requestservicegetter.py index 78181e224..6588bdb9f 100644 --- a/request-management-api/request_api/services/foirequest/requestservicegetter.py +++ b/request-management-api/request_api/services/foirequest/requestservicegetter.py @@ -168,6 +168,7 @@ def __preparebaseinfo(self,request,foiministryrequestid,requestministry,requestm 'selectedMinistries':[{'code':requestministry['programarea.bcgovcode'],'id':requestministry['foiministryrequestid'],'name':requestministry['programarea.name'],'selected':'true'}], 'divisions': self.getdivisions(requestministrydivisions), 'isoipcreview': requestministry['isoipcreview'], + 'isreopened': self.hasreopened(foiministryrequestid), 'oipcdetails': self.getoipcdetails(foiministryrequestid, requestministry['version']), 'onholdTransitionDate': self.getonholdtransition(foiministryrequestid), 'stateTransition': FOIMinistryRequest.getstatesummary(foiministryrequestid), @@ -268,6 +269,14 @@ def getministryrequest(self, foiministryrequestid): def __genericdateformat(self): return '%Y-%m-%d' + def hasreopened(self, requestid): + states = FOIMinistryRequest.getstatesummary(requestid) + if len(states) > 0: + current_state = states[0] + if current_state != "Closed" and any(state['status'] == "Closed" for state in states): + return True + return False + def __prepareapplicant(self,firstname= None, middlename= None, lastname= None, businessname= None): return { 'firstName': firstname, diff --git a/request-management-api/request_api/services/notifications/notificationconfig.py b/request-management-api/request_api/services/notifications/notificationconfig.py index 522ba1749..318f5a536 100644 --- a/request-management-api/request_api/services/notifications/notificationconfig.py +++ b/request-management-api/request_api/services/notifications/notificationconfig.py @@ -43,7 +43,11 @@ def getnotificationtypeid(self, notificationtype): elif notificationtype == "Payment": return 17 elif notificationtype == "Section 5 Pending Reminder": - return 20 + return 20 + elif notificationtype == "OIPC": + return 21 + elif notificationtype == "OIPC Due Reminder": + return 22 return 0 def getnotificationusertypeid(self, notificationusertype): diff --git a/request-management-api/request_api/services/requestservice.py b/request-management-api/request_api/services/requestservice.py index 83d6bf039..99248b3d9 100644 --- a/request-management-api/request_api/services/requestservice.py +++ b/request-management-api/request_api/services/requestservice.py @@ -139,10 +139,14 @@ def calculateduedate(self, ministryrequestid, foirequest, paymentdate): def __skipduedatecalculation(self, ministryrequestid, offholddate): previousoffholddate = FOIMinistryRequest.getlastoffholddate(ministryrequestid) + foiministry_request = FOIMinistryRequest.getrequest(ministryrequestid) + request_reopened = self.__hasreopened(ministryrequestid, "ministryrequest") if previousoffholddate not in (None, ''): previouspaymentdate_pst = datetimehandler().convert_to_pst(previousoffholddate) if datetimehandler().getdate(previouspaymentdate_pst).date() == datetimehandler().getdate(offholddate).date(): return True + if foiministry_request['isoipcreview'] == True and request_reopened: + return True return False def __isincludeoffhold(self): @@ -165,4 +169,14 @@ def saverestrictedrequest(self,ministryrequestid,type, isrestricted,userid): version = FOIMinistryRequest.getversionforrequest(ministryrequestid) FOIRestrictedMinistryRequest.disablerestrictedrequests(ministryrequestid,type,userid) return FOIRestrictedMinistryRequest.saverestrictedrequest(ministryrequestid,type,isrestricted, version, userid) - + + def __hasreopened(self, requestid, requesttype): + if requesttype == "rawrequest": + states = FOIRawRequest.getstatesummary(requestid) + else: + states = FOIMinistryRequest.getstatesummary(requestid) + if len(states) > 0: + current_state = states[0] + if current_state != "Closed" and any(state['status'] == "Closed" for state in states): + return True + return False diff --git a/request-management-api/request_api/utils/enums.py b/request-management-api/request_api/utils/enums.py index f21d807ab..2bad91da1 100644 --- a/request-management-api/request_api/utils/enums.py +++ b/request-management-api/request_api/utils/enums.py @@ -132,6 +132,7 @@ class CommentType(Enum): UserComment = 1 SystemGenerated = 2 DivisionStages = 3 + OIPC = 4 class DocumentPathMapperCategory(Enum): Attachments = "Attachments"