| @@ -516,6 +516,20 @@ function Header(props) { | |||||
| {isGranted("MAINTAIN_SETTING") ? ( | {isGranted("MAINTAIN_SETTING") ? ( | ||||
| <> | <> | ||||
| <li> | |||||
| <Link className="systemSetting" to="/setting/hkidKeyMigration"> | |||||
| <Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}> | |||||
| HKID Key Migration | |||||
| </Typography> | |||||
| </Link> | |||||
| </li> | |||||
| <li> | |||||
| <Link className="systemSetting" to="/setting/userPiiEncryption"> | |||||
| <Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}> | |||||
| User PII Encryption | |||||
| </Typography> | |||||
| </Link> | |||||
| </li> | |||||
| <li> | <li> | ||||
| <Link className="systemSetting" to="/setting/sys"> | <Link className="systemSetting" to="/setting/sys"> | ||||
| <Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}> | <Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}> | ||||
| @@ -3,24 +3,33 @@ import { | |||||
| Grid, | Grid, | ||||
| Typography, | Typography, | ||||
| FormLabel, | FormLabel, | ||||
| Button | |||||
| Button, | |||||
| Dialog, | |||||
| DialogTitle, | |||||
| DialogContent, | |||||
| DialogActions, | |||||
| Box | |||||
| } from '@mui/material'; | } from '@mui/material'; | ||||
| import * as React from "react"; | import * as React from "react"; | ||||
| import * as FormatUtils from "utils/FormatUtils"; | import * as FormatUtils from "utils/FormatUtils"; | ||||
| import * as PaymentStatus from "utils/statusUtils/PaymentStatus"; | import * as PaymentStatus from "utils/statusUtils/PaymentStatus"; | ||||
| import * as DateUtils from "utils/DateUtils"; | import * as DateUtils from "utils/DateUtils"; | ||||
| import * as HttpUtils from "utils/HttpUtils"; | |||||
| import { PAYMENT_MARK_AS_PAID } from "utils/ApiPathConst"; | |||||
| import Loadable from 'components/Loadable'; | import Loadable from 'components/Loadable'; | ||||
| const MainCard = Loadable(React.lazy(() => import('components/MainCard'))); | const MainCard = Loadable(React.lazy(() => import('components/MainCard'))); | ||||
| const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent'))); | const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent'))); | ||||
| import DownloadIcon from '@mui/icons-material/Download'; | import DownloadIcon from '@mui/icons-material/Download'; | ||||
| import {useIntl} from "react-intl"; | import {useIntl} from "react-intl"; | ||||
| // ==============================|| DASHBOARD - DEFAULT ||============================== // | // ==============================|| DASHBOARD - DEFAULT ||============================== // | ||||
| const PaymentDetails = ({ formData,doPrint,onDownload }) => { | |||||
| const PaymentDetails = ({ formData, doPrint, onDownload, onRefresh }) => { | |||||
| const intl = useIntl(); | const intl = useIntl(); | ||||
| const [data, setData] = React.useState({}); | const [data, setData] = React.useState({}); | ||||
| const [onReady, setOnReady] = React.useState(false); | const [onReady, setOnReady] = React.useState(false); | ||||
| const [confirmOpen, setConfirmOpen] = React.useState(false); | |||||
| const [markingPaid, setMarkingPaid] = React.useState(false); | |||||
| // const { locale } = intl; | // const { locale } = intl; | ||||
| React.useEffect(() => { | React.useEffect(() => { | ||||
| @@ -40,9 +49,29 @@ const PaymentDetails = ({ formData,doPrint,onDownload }) => { | |||||
| if("01" == paymentmethod) return "PPS"; | if("01" == paymentmethod) return "PPS"; | ||||
| if("02" == paymentmethod || "03" == paymentmethod) return "Credit Card"; | if("02" == paymentmethod || "03" == paymentmethod) return "Credit Card"; | ||||
| if("04" == paymentmethod) return "FPS"; | if("04" == paymentmethod) return "FPS"; | ||||
| if (data.payMethod === "04,BCFP,FPS") return "FPS"; | |||||
| return paymentmethod; | return paymentmethod; | ||||
| } | } | ||||
| const showMarkAsPaid = data.status === "REJT" && getPaymentMethod() === "FPS"; | |||||
| const handleMarkAsPaid = () => { | |||||
| setMarkingPaid(true); | |||||
| HttpUtils.post({ | |||||
| url: PAYMENT_MARK_AS_PAID + "/" + data.id, | |||||
| onSuccess: () => { | |||||
| setConfirmOpen(false); | |||||
| setMarkingPaid(false); | |||||
| if (onRefresh) { | |||||
| onRefresh(); | |||||
| } | |||||
| }, | |||||
| onError: () => { | |||||
| setMarkingPaid(false); | |||||
| } | |||||
| }); | |||||
| }; | |||||
| return ( | return ( | ||||
| !onReady ? | !onReady ? | ||||
| <LoadingComponent /> | <LoadingComponent /> | ||||
| @@ -51,9 +80,21 @@ const PaymentDetails = ({ formData,doPrint,onDownload }) => { | |||||
| border={false} | border={false} | ||||
| content={false} | content={false} | ||||
| > | > | ||||
| <Typography variant="h5" sx={{ textAlign: "left", mb: 2, borderBottom: "1px solid black" }}> | |||||
| Payment Details | |||||
| </Typography> | |||||
| <Box sx={{ display: "flex", alignItems: "center", justifyContent: "space-between", mb: 2, borderBottom: "1px solid black" }}> | |||||
| <Typography variant="h5" sx={{ textAlign: "left" }}> | |||||
| Payment Details | |||||
| </Typography> | |||||
| {showMarkAsPaid && ( | |||||
| <Button | |||||
| className="printHidden" | |||||
| variant="contained" | |||||
| color="primary" | |||||
| onClick={() => setConfirmOpen(true)} | |||||
| > | |||||
| Mark as Paid | |||||
| </Button> | |||||
| )} | |||||
| </Box> | |||||
| <form> | <form> | ||||
| <Grid container> | <Grid container> | ||||
| <Grid item xs={12} md={12} > | <Grid item xs={12} md={12} > | ||||
| @@ -116,7 +157,7 @@ const PaymentDetails = ({ formData,doPrint,onDownload }) => { | |||||
| <Grid container > | <Grid container > | ||||
| <Grid item xs={6} md={6} sx={{ml:-5, textAlign: "right" }}> | <Grid item xs={6} md={6} sx={{ml:-5, textAlign: "right" }}> | ||||
| <FormLabel sx={{ color: "#000000" }}> | <FormLabel sx={{ color: "#000000" }}> | ||||
| EGIS Reference No.: | |||||
| Payment Reference No.: | |||||
| </FormLabel> | </FormLabel> | ||||
| </Grid> | </Grid> | ||||
| <Grid item xs={6} md={5} sx={{ml:5, textAlign: "left" }}> | <Grid item xs={6} md={5} sx={{ml:5, textAlign: "left" }}> | ||||
| @@ -176,6 +217,25 @@ const PaymentDetails = ({ formData,doPrint,onDownload }) => { | |||||
| } | } | ||||
| </Grid> | </Grid> | ||||
| </form> | </form> | ||||
| <Dialog | |||||
| open={confirmOpen} | |||||
| onClose={() => !markingPaid && setConfirmOpen(false)} | |||||
| > | |||||
| <DialogTitle>Confirm</DialogTitle> | |||||
| <DialogContent> | |||||
| <Typography variant="h5" sx={{ padding: '16px' }}> | |||||
| {`Are you sure to mark as paid for Payment No. ${data.transNo || data.payload?.transactionid} ?`} | |||||
| </Typography> | |||||
| </DialogContent> | |||||
| <DialogActions> | |||||
| <Button onClick={() => setConfirmOpen(false)} disabled={markingPaid}> | |||||
| <Typography variant="h5">Cancel</Typography> | |||||
| </Button> | |||||
| <Button onClick={handleMarkAsPaid} disabled={markingPaid}> | |||||
| <Typography variant="h5">Confirm</Typography> | |||||
| </Button> | |||||
| </DialogActions> | |||||
| </Dialog> | |||||
| </MainCard> | </MainCard> | ||||
| ); | ); | ||||
| }; | }; | ||||
| @@ -35,6 +35,9 @@ const Index = () => { | |||||
| const params = useParams(); | const params = useParams(); | ||||
| const navigate = useNavigate() | const navigate = useNavigate() | ||||
| const [responeData, setResponeData] = React.useState({}); | |||||
| const [transactionData, setTransactionData] = React.useState({}); | |||||
| const [record, setRecord] = React.useState(); | const [record, setRecord] = React.useState(); | ||||
| const [itemList, setItemList] = React.useState([]); | const [itemList, setItemList] = React.useState([]); | ||||
| const [onReady, setOnReady] = React.useState(false); | const [onReady, setOnReady] = React.useState(false); | ||||
| @@ -47,8 +50,16 @@ const Index = () => { | |||||
| }, []); | }, []); | ||||
| React.useEffect(() => { | React.useEffect(() => { | ||||
| setOnReady(true); | |||||
| }, [record]); | |||||
| if (Object.keys(responeData).length > 0) { | |||||
| setTransactionData(responeData); | |||||
| } | |||||
| }, [responeData]); | |||||
| React.useEffect(() => { | |||||
| if (Object.keys(transactionData).length > 0) { | |||||
| setOnReady(true); | |||||
| } | |||||
| }, [transactionData]); | |||||
| // const handleResize = () => { | // const handleResize = () => { | ||||
| // setDetailsOrder(window.innerWidth > 1023 ? 2 : -1); | // setDetailsOrder(window.innerWidth > 1023 ? 2 : -1); | ||||
| @@ -70,17 +81,40 @@ const Index = () => { | |||||
| const loadForm = () => { | const loadForm = () => { | ||||
| if (params.id > 0) { | if (params.id > 0) { | ||||
| HttpUtils.get({ | HttpUtils.get({ | ||||
| url: UrlUtils.PAYMENT_LOAD + "/" + params.id, | url: UrlUtils.PAYMENT_LOAD + "/" + params.id, | ||||
| onSuccess: (responseData) => { | onSuccess: (responseData) => { | ||||
| if (!responseData.data?.id) { | if (!responseData.data?.id) { | ||||
| navigate("/paymentPage/search"); | navigate("/paymentPage/search"); | ||||
| } | } | ||||
| responseData.data["transDateStr"] = responseData.data.transDateTime; | |||||
| responseData.data["transTimeStr"] = DateUtils.dateFormat(responseData.data.transDateTime, "HH:mm:ss"); | |||||
| setItemList(responseData.paymentItemList) | |||||
| setRecord(responseData.data); | |||||
| if (responseData.data.status == null || responseData.data.status == "INPR") { | |||||
| HttpUtils.post({ | |||||
| url: UrlUtils.PAYMENT_RETRY_STATUS_API, | |||||
| params: { | |||||
| "paymentId": params.id | |||||
| }, | |||||
| onSuccess: function (responseData2) { | |||||
| responseData2.data["transDateStr"] = responseData2.data.transDateTime; | |||||
| responseData2.data["transTimeStr"] = DateUtils.dateFormat(responseData2.data.transDateTime, "HH:mm:ss"); | |||||
| setResponeData(responseData2.transactionData); | |||||
| setItemList(responseData2.paymentItemList); | |||||
| setRecord(responseData2.data); | |||||
| }, | |||||
| onError: function () { | |||||
| responseData.data["transDateStr"] = responseData.data.transDateTime; | |||||
| responseData.data["transTimeStr"] = DateUtils.dateFormat(responseData.data.transDateTime, "HH:mm:ss"); | |||||
| setResponeData(responseData); | |||||
| setItemList(responseData.paymentItemList); | |||||
| setRecord(responseData.data); | |||||
| } | |||||
| }); | |||||
| } else { | |||||
| responseData.data["transDateStr"] = responseData.data.transDateTime; | |||||
| responseData.data["transTimeStr"] = DateUtils.dateFormat(responseData.data.transDateTime, "HH:mm:ss"); | |||||
| setResponeData(responseData); | |||||
| setItemList(responseData.paymentItemList); | |||||
| setRecord(responseData.data); | |||||
| } | |||||
| } | } | ||||
| }); | }); | ||||
| } | } | ||||
| @@ -125,6 +159,7 @@ const Index = () => { | |||||
| formData={record} | formData={record} | ||||
| doPrint={doPrint} | doPrint={doPrint} | ||||
| onDownload={onDownload} | onDownload={onDownload} | ||||
| onRefresh={loadForm} | |||||
| style={{ | style={{ | ||||
| display: "flex", | display: "flex", | ||||
| height: "100%", | height: "100%", | ||||
| @@ -87,7 +87,7 @@ export default function SearchPaymentTable({ searchCriteria, applyGridOnReady, a | |||||
| }, | }, | ||||
| { | { | ||||
| field: 'actions', | field: 'actions', | ||||
| headerName: 'Transaction No.', | |||||
| headerName: 'Payment No.', | |||||
| flex: 1, | flex: 1, | ||||
| minWidth: 200, | minWidth: 200, | ||||
| cellClassName: 'actions', | cellClassName: 'actions', | ||||
| @@ -95,6 +95,12 @@ export default function SearchPaymentTable({ searchCriteria, applyGridOnReady, a | |||||
| return clickableLink('/paymentPage/details/' + params.row.id, params.row.transNo); | return clickableLink('/paymentPage/details/' + params.row.id, params.row.transNo); | ||||
| }, | }, | ||||
| }, | }, | ||||
| { | |||||
| field: 'egisRefNo', | |||||
| headerName: 'Payment Reference No.', | |||||
| flex: 1, | |||||
| minWidth: 200, | |||||
| }, | |||||
| { | { | ||||
| field: 'payMethod', | field: 'payMethod', | ||||
| headerName: 'Payment Method', | headerName: 'Payment Method', | ||||
| @@ -107,7 +113,7 @@ export default function SearchPaymentTable({ searchCriteria, applyGridOnReady, a | |||||
| { | { | ||||
| id: 'transDateTime', | id: 'transDateTime', | ||||
| field: 'transDateTime', | field: 'transDateTime', | ||||
| headerName: 'Transaction Date', | |||||
| headerName: 'Payment Date', | |||||
| flex: 1, | flex: 1, | ||||
| minWidth: 150, | minWidth: 150, | ||||
| @@ -11,6 +11,7 @@ import { FiDataGrid } from "components/FiDataGrid"; | |||||
| import {useTheme} from "@emotion/react"; | import {useTheme} from "@emotion/react"; | ||||
| import {useIntl} from "react-intl"; | import {useIntl} from "react-intl"; | ||||
| import { clickableLink } from 'utils/CommonFunction'; | import { clickableLink } from 'utils/CommonFunction'; | ||||
| import { getPaymentMethodByCode } from "auth/utils"; | |||||
| import {PAYMENT_LIST} from "utils/ApiPathConst"; | import {PAYMENT_LIST} from "utils/ApiPathConst"; | ||||
| // ==============================|| EVENT TABLE ||============================== // | // ==============================|| EVENT TABLE ||============================== // | ||||
| @@ -58,6 +59,12 @@ export default function SearchPublicNoticeTable({ searchCriteria, applyGridOnRea | |||||
| return clickableLink('/paymentPage/details/' + params.row.id, params.row.transNo); | return clickableLink('/paymentPage/details/' + params.row.id, params.row.transNo); | ||||
| }, | }, | ||||
| }, | }, | ||||
| { | |||||
| field: 'egisRefNo', | |||||
| headerName: intl.formatMessage({id: 'paymentRefCode'}), | |||||
| width: isMdOrLg ? 'auto' : 160, | |||||
| flex: isMdOrLg ? 1 : undefined, | |||||
| }, | |||||
| { | { | ||||
| id: 'appNos', | id: 'appNos', | ||||
| field: 'appNos', | field: 'appNos', | ||||
| @@ -69,6 +76,13 @@ export default function SearchPublicNoticeTable({ searchCriteria, applyGridOnRea | |||||
| return <div style={{ margin: 4 }}>{appNo}</div> | return <div style={{ margin: 4 }}>{appNo}</div> | ||||
| }, | }, | ||||
| }, | }, | ||||
| { | |||||
| field: 'payMethod', | |||||
| headerName: intl.formatMessage({id: 'paymentMethod'}), | |||||
| width: isMdOrLg ? 'auto' : 160, | |||||
| flex: isMdOrLg ? 1 : undefined, | |||||
| renderCell: (params) => getPaymentMethodByCode(params?.value), | |||||
| }, | |||||
| { | { | ||||
| id: 'transDateTime', | id: 'transDateTime', | ||||
| field: 'transDateTime', | field: 'transDateTime', | ||||
| @@ -0,0 +1,101 @@ | |||||
| import * as React from "react"; | |||||
| import * as HttpUtils from "utils/HttpUtils"; | |||||
| import * as DateUtils from "utils/DateUtils"; | |||||
| import * as UrlUtils from "utils/ApiPathConst"; | |||||
| import { | |||||
| Grid, Typography, Button, | |||||
| Stack, Box, CircularProgress, | |||||
| } from '@mui/material'; | |||||
| import { notifyActionError } from 'utils/CommonFunction'; | |||||
| import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png' | |||||
| const formatLog = (responData) => { | |||||
| if (responData?.msg && !responData?.log) { | |||||
| return <>{DateUtils.datetimeStr(new Date())}<br/><span style={{ color: "red" }}>Error</span><br/>{responData.msg}</>; | |||||
| } | |||||
| const statusColor = responData?.success ? "green" : "red"; | |||||
| const statusText = responData?.success ? "Success" : "Completed with errors"; | |||||
| const logText = (responData?.log || []).join("\n"); | |||||
| return ( | |||||
| <> | |||||
| {DateUtils.datetimeStr(new Date())}<br/> | |||||
| <span style={{ color: statusColor }}>{responData?.dryRun ? "Dry-run " : ""}{statusText}</span><br/> | |||||
| Total: {responData?.total ?? 0}, OK: {responData?.successCount ?? 0}, Skipped: {responData?.skipped ?? 0}, Failed: {responData?.failed ?? 0}<br/> | |||||
| <span style={{ whiteSpace: "pre-line" }}>{logText}</span> | |||||
| </> | |||||
| ); | |||||
| }; | |||||
| const HkidKeyMigration = () => { | |||||
| const [resultStr, setResultStr] = React.useState(""); | |||||
| const [wait, setWait] = React.useState(false); | |||||
| const BackgroundHead = { | |||||
| backgroundImage: `url(${titleBackgroundImg})`, | |||||
| width: 'auto', | |||||
| height: 'auto', | |||||
| backgroundSize: 'contain', | |||||
| backgroundRepeat: 'no-repeat', | |||||
| backgroundColor: '#0C489E', | |||||
| backgroundPosition: 'right' | |||||
| }; | |||||
| const runMigration = (dryRun) => { | |||||
| setWait(true); | |||||
| HttpUtils.post({ | |||||
| url: `${UrlUtils.HKID_REKEY_MIGRATION}?dryRun=${dryRun}&batchSize=100`, | |||||
| params: {}, | |||||
| onSuccess: function (responData) { | |||||
| setWait(false); | |||||
| setResultStr(formatLog(responData)); | |||||
| }, | |||||
| onError: function () { | |||||
| setWait(false); | |||||
| notifyActionError("HKID re-key migration failed"); | |||||
| } | |||||
| }); | |||||
| }; | |||||
| return ( | |||||
| <Grid container sx={{ minHeight: '87vh', backgroundColor: "backgroundColor.default" }} direction="column"> | |||||
| <Grid item xs={12}> | |||||
| <div style={BackgroundHead}> | |||||
| <Stack direction="row" height='70px' justifyContent="space-between" alignItems="center"> | |||||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ textShadow: "0px 0px 25px #0C489E" }}> | |||||
| HKID Key Migration | |||||
| </Typography> | |||||
| </Stack> | |||||
| </div> | |||||
| </Grid> | |||||
| <Grid item xs={12} sx={{ backgroundColor: '#ffffff', ml: 2, mt: 1 }} width="98%"> | |||||
| <Box sx={{ borderRadius: '10px', backgroundColor: '#fff', p: 4 }}> | |||||
| <Typography variant="body1" sx={{ mb: 2 }}> | |||||
| Re-encrypt identification and checkDigit from the legacy key to the new key. | |||||
| Ensure Tomcat has both <code>security.hkid-secret</code> and <code>security.hkid-secret-legacy</code> configured before running. | |||||
| </Typography> | |||||
| <Stack direction="row" spacing={2}> | |||||
| <Button variant="outlined" size="large" disabled={wait} onClick={() => runMigration(true)}> | |||||
| Dry Run | |||||
| </Button> | |||||
| <Button variant="contained" size="large" disabled={wait} onClick={() => runMigration(false)}> | |||||
| Run Migration | |||||
| </Button> | |||||
| {wait ? <CircularProgress size={32} /> : null} | |||||
| </Stack> | |||||
| </Box> | |||||
| </Grid> | |||||
| <Grid item xs={12} sx={{ backgroundColor: '#ffffff', ml: 2, mt: 1, mb: 2 }} width="98%"> | |||||
| <Box sx={{ borderRadius: '10px', backgroundColor: '#fff', p: 4 }}> | |||||
| <Typography variant="h4">Result:</Typography> | |||||
| <Box sx={{ pl: 2, pt: 2 }}>{resultStr}</Box> | |||||
| </Box> | |||||
| </Grid> | |||||
| </Grid> | |||||
| ); | |||||
| }; | |||||
| export default HkidKeyMigration; | |||||
| @@ -0,0 +1,133 @@ | |||||
| import * as React from "react"; | |||||
| import * as HttpUtils from "utils/HttpUtils"; | |||||
| import * as DateUtils from "utils/DateUtils"; | |||||
| import * as UrlUtils from "utils/ApiPathConst"; | |||||
| import { | |||||
| Grid, Typography, Button, | |||||
| Stack, Box, CircularProgress, | |||||
| } from '@mui/material'; | |||||
| import { notifyActionError } from 'utils/CommonFunction'; | |||||
| import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png' | |||||
| const formatEncryptLog = (responData) => { | |||||
| if (responData?.msg && !responData?.log) { | |||||
| return <>{DateUtils.datetimeStr(new Date())}<br/><span style={{ color: "red" }}>Error</span><br/>{responData.msg}</>; | |||||
| } | |||||
| const statusColor = responData?.success ? "green" : "red"; | |||||
| const statusText = responData?.success ? "Success" : "Completed with errors"; | |||||
| const logText = (responData?.log || []).join("\n"); | |||||
| return ( | |||||
| <> | |||||
| {DateUtils.datetimeStr(new Date())}<br/> | |||||
| <span style={{ color: statusColor }}>{responData?.dryRun ? "Dry-run " : ""}{statusText}</span><br/> | |||||
| Total: {responData?.total ?? 0}, OK: {responData?.successCount ?? 0}, Skipped: {responData?.skipped ?? 0}, Failed: {responData?.failed ?? 0}<br/> | |||||
| <span style={{ whiteSpace: "pre-line" }}>{logText}</span> | |||||
| </> | |||||
| ); | |||||
| }; | |||||
| const formatVerifyLog = (responData) => { | |||||
| const tests = responData?.tests || []; | |||||
| const logText = tests.map(t => `${t.passed ? "PASS" : "FAIL"} - ${t.name}: ${t.message}`).join("\n"); | |||||
| const statusColor = responData?.success ? "green" : "red"; | |||||
| return ( | |||||
| <> | |||||
| {DateUtils.datetimeStr(new Date())}<br/> | |||||
| <span style={{ color: statusColor }}>{responData?.success ? "All tests passed" : "Some tests failed"}</span><br/> | |||||
| Passed: {responData?.passed ?? 0}, Failed: {responData?.failed ?? 0}<br/> | |||||
| <span style={{ whiteSpace: "pre-line" }}>{logText}</span> | |||||
| </> | |||||
| ); | |||||
| }; | |||||
| const UserPiiEncryption = () => { | |||||
| const [resultStr, setResultStr] = React.useState(""); | |||||
| const [wait, setWait] = React.useState(false); | |||||
| const BackgroundHead = { | |||||
| backgroundImage: `url(${titleBackgroundImg})`, | |||||
| width: 'auto', | |||||
| height: 'auto', | |||||
| backgroundSize: 'contain', | |||||
| backgroundRepeat: 'no-repeat', | |||||
| backgroundColor: '#0C489E', | |||||
| backgroundPosition: 'right' | |||||
| }; | |||||
| const runEncrypt = (dryRun) => { | |||||
| setWait(true); | |||||
| HttpUtils.post({ | |||||
| url: `${UrlUtils.USER_PII_ENCRYPT_MIGRATION}?dryRun=${dryRun}&batchSize=100`, | |||||
| params: {}, | |||||
| onSuccess: function (responData) { | |||||
| setWait(false); | |||||
| setResultStr(formatEncryptLog(responData)); | |||||
| }, | |||||
| onError: function () { | |||||
| setWait(false); | |||||
| notifyActionError("User PII encryption failed"); | |||||
| } | |||||
| }); | |||||
| }; | |||||
| const runVerify = () => { | |||||
| setWait(true); | |||||
| HttpUtils.post({ | |||||
| url: UrlUtils.USER_PII_VERIFY_MIGRATION, | |||||
| params: {}, | |||||
| onSuccess: function (responData) { | |||||
| setWait(false); | |||||
| setResultStr(formatVerifyLog(responData)); | |||||
| }, | |||||
| onError: function () { | |||||
| setWait(false); | |||||
| notifyActionError("User PII verification failed"); | |||||
| } | |||||
| }); | |||||
| }; | |||||
| return ( | |||||
| <Grid container sx={{ minHeight: '87vh', backgroundColor: "backgroundColor.default" }} direction="column"> | |||||
| <Grid item xs={12}> | |||||
| <div style={BackgroundHead}> | |||||
| <Stack direction="row" height='70px' justifyContent="space-between" alignItems="center"> | |||||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ textShadow: "0px 0px 25px #0C489E" }}> | |||||
| User PII Encryption | |||||
| </Typography> | |||||
| </Stack> | |||||
| </div> | |||||
| </Grid> | |||||
| <Grid item xs={12} sx={{ backgroundColor: '#ffffff', ml: 2, mt: 1 }} width="98%"> | |||||
| <Box sx={{ borderRadius: '10px', backgroundColor: '#fff', p: 4 }}> | |||||
| <Typography variant="body1" sx={{ mb: 2 }}> | |||||
| Encrypt enName, chName, mobileNumber, and address for existing user records, then verify data retrieval. | |||||
| </Typography> | |||||
| <Stack direction="row" spacing={2} flexWrap="wrap"> | |||||
| <Button variant="outlined" size="large" disabled={wait} onClick={() => runEncrypt(true)}> | |||||
| Dry Run Encrypt | |||||
| </Button> | |||||
| <Button variant="contained" size="large" disabled={wait} onClick={() => runEncrypt(false)}> | |||||
| Run Encrypt | |||||
| </Button> | |||||
| <Button variant="contained" color="secondary" size="large" disabled={wait} onClick={runVerify}> | |||||
| Verify Retrieval | |||||
| </Button> | |||||
| {wait ? <CircularProgress size={32} /> : null} | |||||
| </Stack> | |||||
| </Box> | |||||
| </Grid> | |||||
| <Grid item xs={12} sx={{ backgroundColor: '#ffffff', ml: 2, mt: 1, mb: 2 }} width="98%"> | |||||
| <Box sx={{ borderRadius: '10px', backgroundColor: '#fff', p: 4 }}> | |||||
| <Typography variant="h4">Result:</Typography> | |||||
| <Box sx={{ pl: 2, pt: 2 }}>{resultStr}</Box> | |||||
| </Box> | |||||
| </Grid> | |||||
| </Grid> | |||||
| ); | |||||
| }; | |||||
| export default UserPiiEncryption; | |||||
| @@ -81,7 +81,10 @@ const UserInformationCard_Individual = ({ formData, loadDataFun }) => { | |||||
| addressLine3: yup.string().max(40, getMaxErrStr(40)).nullable(), | addressLine3: yup.string().max(40, getMaxErrStr(40)).nullable(), | ||||
| emailAddress: yup.string().email(intl.formatMessage({ id: 'validEmailFormat' })).max(255).required(intl.formatMessage({ id: 'requireEmail' })), | emailAddress: yup.string().email(intl.formatMessage({ id: 'validEmailFormat' })).max(255).required(intl.formatMessage({ id: 'requireEmail' })), | ||||
| idDocType: yup.string().max(255, getMaxErrStr(255)).required(intl.formatMessage({ id: 'requireIdDocType' })), | idDocType: yup.string().max(255, getMaxErrStr(255)).required(intl.formatMessage({ id: 'requireIdDocType' })), | ||||
| identification: yup.string().required(getRequiredErrStr('number')) | |||||
| identification: yup.string().when('verifiedBy', { | |||||
| is: (verifiedBy) => verifiedBy != null, | |||||
| then: (schema) => schema.notRequired(), | |||||
| otherwise: (schema) => schema.required(getRequiredErrStr('number')) | |||||
| .matches(/^[aA-zZ0-9\s]+$/, { message: displayErrorMsg(`${selectedIdDocInputType}${intl.formatMessage({ id: 'noSpecialCharacter' })}`) }) | .matches(/^[aA-zZ0-9\s]+$/, { message: displayErrorMsg(`${selectedIdDocInputType}${intl.formatMessage({ id: 'noSpecialCharacter' })}`) }) | ||||
| .matches(/^\S*$/, { message: displayErrorMsg(`${selectedIdDocInputType}${intl.formatMessage({ id: 'noSpace' })}`) }) | .matches(/^\S*$/, { message: displayErrorMsg(`${selectedIdDocInputType}${intl.formatMessage({ id: 'noSpace' })}`) }) | ||||
| .test('checkIDCardFormat', displayErrorMsg(`${intl.formatMessage({ id: 'requiredValid' })}${selectedIdDocInputType}${intl.formatMessage({ id: 'number' })}`), function (value) { | .test('checkIDCardFormat', displayErrorMsg(`${intl.formatMessage({ id: 'requiredValid' })}${selectedIdDocInputType}${intl.formatMessage({ id: 'number' })}`), function (value) { | ||||
| @@ -133,8 +136,12 @@ const UserInformationCard_Individual = ({ formData, loadDataFun }) => { | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| }) | |||||
| }), | }), | ||||
| checkDigit: yup.string().max(1, getMaxErrStr(1)).nullable() | |||||
| checkDigit: yup.string().when('verifiedBy', { | |||||
| is: (verifiedBy) => verifiedBy != null, | |||||
| then: (schema) => schema.notRequired(), | |||||
| otherwise: (schema) => schema.max(1, getMaxErrStr(1)).nullable() | |||||
| .matches(/^[A-Z0-9\s]+$/, { message: displayErrorMsg(`${selectedIdDocInputType}${intl.formatMessage({ id: 'noSpecialCharacter' })}`) }) | .matches(/^[A-Z0-9\s]+$/, { message: displayErrorMsg(`${selectedIdDocInputType}${intl.formatMessage({ id: 'noSpecialCharacter' })}`) }) | ||||
| .test('checkIDCardFormat', displayErrorMsg(`${intl.formatMessage({ id: 'requiredNumberInQuote' })}`), function (value) { | .test('checkIDCardFormat', displayErrorMsg(`${intl.formatMessage({ id: 'requiredNumberInQuote' })}`), function (value) { | ||||
| // console.log(selectedIdDocInputType) | // console.log(selectedIdDocInputType) | ||||
| @@ -162,7 +169,8 @@ const UserInformationCard_Individual = ({ formData, loadDataFun }) => { | |||||
| return false | return false | ||||
| } | } | ||||
| } | } | ||||
| }), | |||||
| }) | |||||
| }), | |||||
| tel_countryCode: yup.string().min(3, intl.formatMessage({ id: 'require3Number' })).required(intl.formatMessage({ id: 'requireDialingCode' })), | tel_countryCode: yup.string().min(3, intl.formatMessage({ id: 'require3Number' })).required(intl.formatMessage({ id: 'requireDialingCode' })), | ||||
| fax_countryCode: yup.string().min(3, intl.formatMessage({ id: 'require3Number' })), | fax_countryCode: yup.string().min(3, intl.formatMessage({ id: 'require3Number' })), | ||||
| phoneNumber: yup.string().min(8, intl.formatMessage({ id: 'require8Number' })).required(intl.formatMessage({ id: 'requireContactNumber' })), | phoneNumber: yup.string().min(8, intl.formatMessage({ id: 'require8Number' })).required(intl.formatMessage({ id: 'requireContactNumber' })), | ||||
| @@ -186,8 +194,10 @@ const UserInformationCard_Individual = ({ formData, loadDataFun }) => { | |||||
| countryCode: values.tel_countryCode, | countryCode: values.tel_countryCode, | ||||
| phoneNumber: values.phoneNumber | phoneNumber: values.phoneNumber | ||||
| }, | }, | ||||
| identification: values.identification, | |||||
| checkDigit: values.checkDigit, | |||||
| ...(values.verifiedBy == null ? { | |||||
| identification: values.identification, | |||||
| checkDigit: values.checkDigit, | |||||
| } : {}), | |||||
| faxNo: { | faxNo: { | ||||
| countryCode: values.fax_countryCode, | countryCode: values.fax_countryCode, | ||||
| faxNumber: values.faxNumber | faxNumber: values.faxNumber | ||||
| @@ -471,6 +481,11 @@ const UserInformationCard_Individual = ({ formData, loadDataFun }) => { | |||||
| </Grid> | </Grid> | ||||
| <Grid item xs={12} sm={12} md={9} lg={6}> | <Grid item xs={12} sm={12} md={9} lg={6}> | ||||
| {currentUserData.verifiedBy ? | |||||
| <Typography variant="h5" mt={1}> | |||||
| Hidden for security purpose | |||||
| </Typography> | |||||
| : | |||||
| <Grid container> | <Grid container> | ||||
| {formik.values.idDocType === "HKID" ? | {formik.values.idDocType === "HKID" ? | ||||
| editMode ? | editMode ? | ||||
| @@ -549,6 +564,7 @@ const UserInformationCard_Individual = ({ formData, loadDataFun }) => { | |||||
| </Stack> | </Stack> | ||||
| } | } | ||||
| </Grid> | </Grid> | ||||
| } | |||||
| </Grid> | </Grid> | ||||
| </Grid> | </Grid> | ||||
| </Grid> | </Grid> | ||||
| @@ -2,8 +2,6 @@ | |||||
| import { | import { | ||||
| Grid, Button, Typography, | Grid, Button, Typography, | ||||
| FormHelperText, | FormHelperText, | ||||
| Stack, | |||||
| IconButton | |||||
| } from '@mui/material'; | } from '@mui/material'; | ||||
| import MainCard from "components/MainCard"; | import MainCard from "components/MainCard"; | ||||
| import * as React from "react"; | import * as React from "react"; | ||||
| @@ -23,7 +21,6 @@ import { PRIMARY_CONTAINED_BUTTON_SX } from 'themes/colorConst'; | |||||
| import {FormattedMessage, useIntl} from "react-intl"; | import {FormattedMessage, useIntl} from "react-intl"; | ||||
| import {PNSPS_BUTTON_THEME} from "../../../themes/buttonConst"; | import {PNSPS_BUTTON_THEME} from "../../../themes/buttonConst"; | ||||
| import {ThemeProvider} from "@emotion/react"; | import {ThemeProvider} from "@emotion/react"; | ||||
| import { EyeInvisibleOutlined, EyeOutlined } from '@ant-design/icons'; | |||||
| // ==============================|| DASHBOARD - DEFAULT ||============================== // | // ==============================|| DASHBOARD - DEFAULT ||============================== // | ||||
| @@ -34,15 +31,6 @@ const UserInformationCard_Individual_Pub = ({ formData, loadDataFun }) => { | |||||
| const [editMode, setEditMode] = useState(false); | const [editMode, setEditMode] = useState(false); | ||||
| const [onReady, setOnReady] = useState(false); | const [onReady, setOnReady] = useState(false); | ||||
| const [errorMsg, setErrorMsg] = useState(""); | const [errorMsg, setErrorMsg] = useState(""); | ||||
| const [showId, setshowId] = useState(false); | |||||
| const handleClickShowId = () => { | |||||
| setshowId(!showId); | |||||
| }; | |||||
| const handleMouseDownId = (event) => { | |||||
| event.preventDefault(); | |||||
| }; | |||||
| useEffect(() => { | useEffect(() => { | ||||
| if (Object.keys(formData).length > 0) { | if (Object.keys(formData).length > 0) { | ||||
| @@ -252,79 +240,9 @@ const UserInformationCard_Individual_Pub = ({ formData, loadDataFun }) => { | |||||
| </Grid> | </Grid> | ||||
| <Grid item xs={12} sm={12} md={9} lg={6}> | <Grid item xs={12} sm={12} md={9} lg={6}> | ||||
| <Grid container> | |||||
| {formik.values.idDocType === "HKID" ? | |||||
| // <> | |||||
| // <Grid item xs={6} sm={6} md={6} lg={7.5} sx={{mr:1}}> | |||||
| // {FieldUtils.initField({ | |||||
| // valueName: "identification", | |||||
| // disabled: true, | |||||
| // form: formik, | |||||
| // placeholder: intl.formatMessage({id: 'idDocNumber'}), | |||||
| // inputProps: { | |||||
| // maxLength: 7, | |||||
| // onKeyDown: (e) => { | |||||
| // if (e.key === 'Enter') { | |||||
| // e.preventDefault(); | |||||
| // } | |||||
| // }, | |||||
| // } | |||||
| // })} | |||||
| // </Grid> | |||||
| // <Grid item xs={2} sm={2} md={2} lg={2} style={{minWidth:40}}> | |||||
| // {FieldUtils.initField({ | |||||
| // valueName: "checkDigit", | |||||
| // disabled: true, | |||||
| // form: formik, | |||||
| // })} | |||||
| // </Grid> | |||||
| // </> | |||||
| <Stack direction="row"> | |||||
| <Typography variant="h5" mt={1}> | |||||
| {formik.values.identification?.slice(0, 4)} | |||||
| </Typography> | |||||
| <Typography variant="h5"mt={1}> | |||||
| {/* {showId ?formik.values.identification.slice(4):"****"}{showId ? '(' + formik.values.checkDigit + ')' :null} */} | |||||
| {showId ? formik.values.identification?.slice(4) : "****"}{showId ? formik.values.checkDigit?'(' +formik.values.checkDigit+ ')': "()" : ""} | |||||
| </Typography> | |||||
| <IconButton | |||||
| aria-label={intl.formatMessage({ id: 'ariaToggleIdVisibility' })} | |||||
| onClick={handleClickShowId} | |||||
| onMouseDown={handleMouseDownId} | |||||
| edge="end" | |||||
| size="large" | |||||
| > | |||||
| {showId ? <EyeOutlined /> : <EyeInvisibleOutlined />} | |||||
| </IconButton> | |||||
| </Stack> | |||||
| : | |||||
| // <Grid item xs={10} sm={4} md={4} lg={10}> | |||||
| // {FieldUtils.initField({ | |||||
| // valueName: "identification", | |||||
| // disabled: true, | |||||
| // form: formik | |||||
| // })} | |||||
| // </Grid> | |||||
| <Stack direction="row"> | |||||
| <Typography variant="h5" mt={1}> | |||||
| {formik.values.identification?.slice(0, 4)} | |||||
| </Typography> | |||||
| <Typography variant="h5"mt={1}> | |||||
| {showId ?formik.values.identification?.slice(4):"****"} | |||||
| </Typography> | |||||
| <IconButton | |||||
| aria-label={intl.formatMessage({ id: 'ariaToggleIdVisibility' })} | |||||
| onClick={handleClickShowId} | |||||
| onMouseDown={handleMouseDownId} | |||||
| edge="end" | |||||
| size="large" | |||||
| > | |||||
| {showId ? <EyeOutlined /> : <EyeInvisibleOutlined />} | |||||
| </IconButton> | |||||
| </Stack> | |||||
| } | |||||
| </Grid> | |||||
| <Typography variant="h5" mt={1}> | |||||
| {formik.values.identification?.slice(0, 4)} | |||||
| </Typography> | |||||
| </Grid> | </Grid> | ||||
| </Grid> | </Grid> | ||||
| </Grid> | </Grid> | ||||
| @@ -30,6 +30,8 @@ const EmailTemplateDetailPage = Loadable(lazy(() => import('pages/EmailTemplate/ | |||||
| const HolidayPage = Loadable(lazy(() => import('pages/Holiday'))); | const HolidayPage = Loadable(lazy(() => import('pages/Holiday'))); | ||||
| const GazetteIssuePage = Loadable(lazy(() => import('pages/GazetteIssue/index'))); | const GazetteIssuePage = Loadable(lazy(() => import('pages/GazetteIssue/index'))); | ||||
| const DrImport = Loadable(lazy(() => import('pages/Setting/DrImport'))); | const DrImport = Loadable(lazy(() => import('pages/Setting/DrImport'))); | ||||
| const HkidKeyMigration = Loadable(lazy(() => import('pages/Setting/HkidKeyMigration'))); | |||||
| const UserPiiEncryption = Loadable(lazy(() => import('pages/Setting/UserPiiEncryption'))); | |||||
| const AuditLogPage = Loadable(lazy(() => import('pages/AuditLog/index'))); | const AuditLogPage = Loadable(lazy(() => import('pages/AuditLog/index'))); | ||||
| const ReconReportPage = Loadable(lazy(() => import('pages/Recon'))); | const ReconReportPage = Loadable(lazy(() => import('pages/Recon'))); | ||||
| const ChangePasswordPage = Loadable(lazy(() => import('pages/User/ChangePasswordPage'))); | const ChangePasswordPage = Loadable(lazy(() => import('pages/User/ChangePasswordPage'))); | ||||
| @@ -190,6 +192,18 @@ const GLDUserRoutes = { | |||||
| element: <DrImport /> | element: <DrImport /> | ||||
| }:{}, | }:{}, | ||||
| isGranted("MAINTAIN_SETTING")? | |||||
| { | |||||
| path: '/setting/hkidKeyMigration', | |||||
| element: <HkidKeyMigration /> | |||||
| }:{}, | |||||
| isGranted("MAINTAIN_SETTING")? | |||||
| { | |||||
| path: '/setting/userPiiEncryption', | |||||
| element: <UserPiiEncryption /> | |||||
| }:{}, | |||||
| isGranted("MAINTAIN_SETTING")? | isGranted("MAINTAIN_SETTING")? | ||||
| { | { | ||||
| path: '/setting/auditLog', | path: '/setting/auditLog', | ||||
| @@ -421,7 +421,7 @@ | |||||
| "payTotal": "Total Payment Amount", | "payTotal": "Total Payment Amount", | ||||
| "payDetail": "Payment Details", | "payDetail": "Payment Details", | ||||
| "payMethod": "Payment methods", | "payMethod": "Payment methods", | ||||
| "epayMethod": " e-Payment Method", | |||||
| "epayMethod": " Payment Method", | |||||
| "selectPaymentMethod": "Please select a payment method", | "selectPaymentMethod": "Please select a payment method", | ||||
| "selectPaymentMethodBtn": "Select payment method", | "selectPaymentMethodBtn": "Select payment method", | ||||
| "payReceipt": "Payment Receipt", | "payReceipt": "Payment Receipt", | ||||
| @@ -448,7 +448,7 @@ | |||||
| "paymentLimitPrice2":" is only applicable when minimum amount is HK$0.10 and maximum amount is HK$9,999,999.99", | "paymentLimitPrice2":" is only applicable when minimum amount is HK$0.10 and maximum amount is HK$9,999,999.99", | ||||
| "paymentLimitPPS":" Payment could not be made via mobile device browsers, please use desktop computers to make payment.", | "paymentLimitPPS":" Payment could not be made via mobile device browsers, please use desktop computers to make payment.", | ||||
| "paymentMethod": "Payment Method", | "paymentMethod": "Payment Method", | ||||
| "paymentProcessLimited":"Payment process must be completed within 30 minutes and return to this system.", | |||||
| "paymentProcessLimited":"Please complete the payment process within 15 minutes. Note: For FPS payments, scanning, payment and all necessary approvals must be finished within 3 minutes due to security-related QR code expiry.", | |||||
| "publicNoticeDetailTitle": "Public Notice Application Information", | "publicNoticeDetailTitle": "Public Notice Application Information", | ||||
| "applyPerson": "Applicant", | "applyPerson": "Applicant", | ||||
| @@ -454,7 +454,7 @@ | |||||
| "payTotal": "付款总额", | "payTotal": "付款总额", | ||||
| "payDetail": "付款详情", | "payDetail": "付款详情", | ||||
| "payMethod": "付款方式", | "payMethod": "付款方式", | ||||
| "epayMethod": "电子付款方法", | |||||
| "epayMethod": "付款方法", | |||||
| "selectPaymentMethod": "请选择付款方法", | "selectPaymentMethod": "请选择付款方法", | ||||
| "selectPaymentMethodBtn": "选择付款方法", | "selectPaymentMethodBtn": "选择付款方法", | ||||
| "payReceipt": "付款收据", | "payReceipt": "付款收据", | ||||
| @@ -482,7 +482,7 @@ | |||||
| "paymentLimitPrice2":"只适用于最小金额为 0.10 港元及最高金额为 9,999,999.99港元", | "paymentLimitPrice2":"只适用于最小金额为 0.10 港元及最高金额为 9,999,999.99港元", | ||||
| "paymentLimitPPS":"付款不适用于流动装置的浏览器,请使用桌面电脑。", | "paymentLimitPPS":"付款不适用于流动装置的浏览器,请使用桌面电脑。", | ||||
| "paymentMethod": "付款方式", | "paymentMethod": "付款方式", | ||||
| "paymentProcessLimited":"付款过程必须在 30 分钟内完成及返回本系统。", | |||||
| "paymentProcessLimited":"请于15分钟内完成付款程序。 注意:使用转数快(FPS)时,因二维码具安全时效限制,须于3分钟内完成扫码、付款及所有相关审核程序。", | |||||
| "publicNoticeDetailTitle": "公共启事申请资料", | "publicNoticeDetailTitle": "公共启事申请资料", | ||||
| "applyPerson": "申请人", | "applyPerson": "申请人", | ||||
| @@ -455,7 +455,7 @@ | |||||
| "payTotal": "付款總額", | "payTotal": "付款總額", | ||||
| "payDetail": "付款詳情", | "payDetail": "付款詳情", | ||||
| "payMethod": "付款方式", | "payMethod": "付款方式", | ||||
| "epayMethod": "電子付款方法", | |||||
| "epayMethod": "付款方法", | |||||
| "selectPaymentMethod": "請選擇付款方法", | "selectPaymentMethod": "請選擇付款方法", | ||||
| "selectPaymentMethodBtn": "選擇付款方法", | "selectPaymentMethodBtn": "選擇付款方法", | ||||
| "payReceipt": "付款收據", | "payReceipt": "付款收據", | ||||
| @@ -483,7 +483,7 @@ | |||||
| "paymentLimitPrice2":"只適用於最小金額為 0.10 港元及最高金額為 9,999,999.99港元", | "paymentLimitPrice2":"只適用於最小金額為 0.10 港元及最高金額為 9,999,999.99港元", | ||||
| "paymentLimitPPS":"付款不適用於流動裝置的瀏覽器,請使用桌面電腦。", | "paymentLimitPPS":"付款不適用於流動裝置的瀏覽器,請使用桌面電腦。", | ||||
| "paymentMethod": "付款方法", | "paymentMethod": "付款方法", | ||||
| "paymentProcessLimited":"付款程序必須在 30 分鐘內完成及返回本系统。", | |||||
| "paymentProcessLimited":"請於15分鐘內完成付款程序。 注意:使用轉數快(FPS)時,因二維碼具安全時效限制,須於3分鐘內完成掃碼、付款及所有相關審核程序。", | |||||
| "publicNoticeDetailTitle": "公共啟事申請資料", | "publicNoticeDetailTitle": "公共啟事申請資料", | ||||
| "applyPerson": "申請人", | "applyPerson": "申請人", | ||||
| @@ -84,6 +84,9 @@ export const GET_FILE_DELETE = apiPath+'/file/delete'; | |||||
| export const DR_EXPORT = apiPath+'/settings/dr/export'; | export const DR_EXPORT = apiPath+'/settings/dr/export'; | ||||
| export const DR_IMPORT = apiPath+'/settings/dr/import'; | export const DR_IMPORT = apiPath+'/settings/dr/import'; | ||||
| export const OFFLINE_IMPORT = apiPath+'/settings/dr/importOffline'; | export const OFFLINE_IMPORT = apiPath+'/settings/dr/importOffline'; | ||||
| export const HKID_REKEY_MIGRATION = apiPath+'/settings/migration/hkid-rekey'; | |||||
| export const USER_PII_ENCRYPT_MIGRATION = apiPath+'/settings/migration/user-pii-encrypt'; | |||||
| export const USER_PII_VERIFY_MIGRATION = apiPath+'/settings/migration/user-pii-verify'; | |||||
| export const AUDIT_LOG_EXPORT = apiPath+'/settings/auditLog-export'; | export const AUDIT_LOG_EXPORT = apiPath+'/settings/auditLog-export'; | ||||
| @@ -180,6 +183,7 @@ export const PAYMENT_LOAD = apiPath+'/payment/load';//GET | |||||
| export const PAYMENT_APP_LIST = apiPath+'/payment/applist';//POST | export const PAYMENT_APP_LIST = apiPath+'/payment/applist';//POST | ||||
| export const PAYMENT_CHECK = apiPath+'/payment/check-payment';//GET | export const PAYMENT_CHECK = apiPath+'/payment/check-payment';//GET | ||||
| export const PAYMENT_BIB = apiPath+'/payment/set-bib';//POST | export const PAYMENT_BIB = apiPath+'/payment/set-bib';//POST | ||||
| export const PAYMENT_MARK_AS_PAID = apiPath+'/payment/mark-as-paid';//POST | |||||
| export const PAYMENT_GFMIS_LIST = apiPath+'/payment/listGFMIS';//GET | export const PAYMENT_GFMIS_LIST = apiPath+'/payment/listGFMIS';//GET | ||||
| export const PAYMENT_LIMIT_SETTING_LIST = apiPath+'/settings/payment';//GET | export const PAYMENT_LIMIT_SETTING_LIST = apiPath+'/settings/payment';//GET | ||||