From d07e18904e337cce061367c3ebd360ee1eeccc2a Mon Sep 17 00:00:00 2001 From: Alex Cheung Date: Thu, 16 May 2024 15:59:15 +0800 Subject: [PATCH] update revoke --- src/layout/MainLayout/Header/index.js | 36 +- .../Details_GLD/ApplicationDetailCard.js | 16 + src/pages/PublicNotice/Details_GLD/index.js | 20 +- .../Search_Mark_As_Paid_GLD/DataGrid.js | 251 +++++++++++ .../Search_Mark_As_Paid_GLD/SearchForm.js | 389 ++++++++++++++++++ .../Search_Mark_As_Paid_GLD/index.js | 113 +++++ src/routes/GLDUserRoutes.js | 7 + src/utils/ApiPathConst.js | 4 + 8 files changed, 825 insertions(+), 11 deletions(-) create mode 100644 src/pages/PublicNotice/Search_Mark_As_Paid_GLD/DataGrid.js create mode 100644 src/pages/PublicNotice/Search_Mark_As_Paid_GLD/SearchForm.js create mode 100644 src/pages/PublicNotice/Search_Mark_As_Paid_GLD/index.js diff --git a/src/layout/MainLayout/Header/index.js b/src/layout/MainLayout/Header/index.js index 2f570ba..9824011 100644 --- a/src/layout/MainLayout/Header/index.js +++ b/src/layout/MainLayout/Header/index.js @@ -107,24 +107,39 @@ function Header(props) {
  • Payment
      + { + isGranted("MAINTAIN_DEMANDNOTE") ? +
    • + Export for GDN +
    • + : + <> + } + { isGranted("MAINTAIN_PAYMENT") ?
    • - Online Payment Record + Mark Payment
    • : <> } + { + isGranted("MAINTAIN_PAYMENT") ? +
    • + Online Payment Record +
    • + : + <> + } + { isGranted("MAINTAIN_RECON") ? <>
    • GFMIS Generate XML
    • -
    • - Recon Report -
    • : @@ -148,15 +163,18 @@ function Header(props) { : <> } +{ + isGranted("MAINTAIN_RECON") ? + <> +
    • + Recon Report +
    • + - { - isGranted("MAINTAIN_DEMANDNOTE") ? -
    • - Export for GDN -
    • : <> } +
  • diff --git a/src/pages/PublicNotice/Details_GLD/ApplicationDetailCard.js b/src/pages/PublicNotice/Details_GLD/ApplicationDetailCard.js index 4f6533f..35f3083 100644 --- a/src/pages/PublicNotice/Details_GLD/ApplicationDetailCard.js +++ b/src/pages/PublicNotice/Details_GLD/ApplicationDetailCard.js @@ -117,6 +117,10 @@ const ApplicationDetailCard = ( setStatus("publish") } + const revokeClick = () => () => { + setStatus("revoke") + }; + const onProofClick = () => { if (applicationDetailData.data.groupNo) { HttpUtils.get({ @@ -264,6 +268,18 @@ const ApplicationDetailCard = ( ( (currentApplicationDetailData.status == "paid" && currentApplicationDetailData.creditor == 0) ? <> + {title} diff --git a/src/pages/PublicNotice/Search_Mark_As_Paid_GLD/DataGrid.js b/src/pages/PublicNotice/Search_Mark_As_Paid_GLD/DataGrid.js new file mode 100644 index 0000000..b86bad4 --- /dev/null +++ b/src/pages/PublicNotice/Search_Mark_As_Paid_GLD/DataGrid.js @@ -0,0 +1,251 @@ +// material-ui +import * as React from 'react'; +import { + //Link, + Button, + Grid, + Typography, + Stack, + Dialog, DialogTitle, DialogContent, DialogActions, +} from '@mui/material'; +import { + // GET_PUBLIC_NOTICE_LIST, + SET_PUBLIC_NOTICE_STATUS_MARK_AS_PAID, + GET_PUBLIC_NOTICE_OFFLINE_PAYMENT_LIST } from "utils/ApiPathConst"; +import * as HttpUtils from "utils/HttpUtils"; +import * as DateUtils from "utils/DateUtils"; +import * as FormatUtils from "utils/FormatUtils"; +// import * as StatusUtils from "utils/statusUtils/PublicNoteStatusUtils"; +import { useNavigate } from "react-router-dom"; +import { FiDataGrid } from "components/FiDataGrid"; +import { notifyActionSuccess, clickableLink } from 'utils/CommonFunction'; +import { FormattedMessage, useIntl } from "react-intl"; +import * as utils from "auth/utils" +// ==============================|| EVENT TABLE ||============================== // + +export default function SearchPublicNoticeTable({ searchCriteria }) { + + const [rows, setRows] = React.useState([]); + const navigate = useNavigate() + + const [selectedRowItems, setSelectedRowItems] = React.useState([]); + const [isConfirmPopUp, setIsConfirmPopUp] = React.useState(false); + const [isWarningPopUp, setIsWarningPopUp] = React.useState(false); + + const intl = useIntl(); + + const [_searchCriteria, set_searchCriteria] = React.useState(searchCriteria); + React.useEffect(() => { + set_searchCriteria(searchCriteria); + }, [searchCriteria]); + + + function genIssueNo(params) { + const issueNo = params.row.issueYear + " Vol. " + FormatUtils.zeroPad(params.row.issueVolume, 3) + ", No. " + FormatUtils.zeroPad(params.row.issueNo, 2) + ", " + DateUtils.dateFormat(params.row.issueDate, "D MMM YYYY (ddd)") + return issueNo + } + + function genGroupNo(params) { + let groupNo = params.row.groupNo + if (groupNo != null) { + groupNo = <>
    {groupNo}
    + } + return groupNo + } + + const columns = [ + { + field: 'actions', + headerName: 'Application No.', + sortable: false, + width: 150, + cellClassName: 'actions', + renderCell: (params) => { + return clickableLink('/application/' + params.id, params.row.appNo); + }, + }, + { + id: 'contactPerson', + field: 'contactPerson', + headerName: 'Customer Name', + flex: 1, + minWidth: 50, + renderCell: (params) => { + let company = params.row.enCompanyName != null ? params.row.enCompanyName : params.row.chCompanyName; + company = company != null ? company : ""; + if (params.row.sysType != null && params.row.sysType == "dummy"){ + company = params.row.contactPerson + } + return
    + {company} +
    ; + } + }, + { + id: 'issueNoAndCode', + field: 'issueNoAndCode', + headerName: 'Gazette Issue No. / Gazette Code', + sortable: false, + flex: 1.5, + minWidth: 350, + renderCell: (params) => ( +
    + {genIssueNo(params)} + {genGroupNo(params)} +
    + + ) + }, + { + id: 'paymentMethod', + field: 'paymentMethod', + headerName: 'Payment Method', + sortable: false, + minWidth: 250, + flex: 2, + renderCell: (params) => { + let paymentMethod = params.row.paymentMethod!=null?intl.formatMessage({ id: utils.getPaymentMethod(params.row.paymentMethod)}):"" + return (<> + {paymentMethod} + ); + } + }, + { + id: 'fee', + field: 'fee', + headerName: 'Amount(HK$)', + flex: 1, + minWidth: 100, + valueGetter: (params) => { + return FormatUtils.currencyFormat(params?.value); + } + }, + + ]; + + function handleRowDoubleClick(params) { + // handleEditClick(params) + navigate('/application/' + params.id); + } + + const doPublish = () => { + setIsConfirmPopUp(false); + let appIdList = []; + const datas = rows?.filter((row) => + selectedRowItems.includes(row.id) + ); + // console.log(datas) + for (var i = 0; i < datas?.length; i++) { + appIdList.push(datas[i].id); + } + if (appIdList.length < 1) { + setIsWarningPopUp(true); + } else { + HttpUtils.post({ + url: SET_PUBLIC_NOTICE_STATUS_MARK_AS_PAID, + params: { + ids: appIdList + }, + onSuccess: () => { + searchCriteria.reload = new Date(); + notifyActionSuccess("Action Success!") + location.reload() + } + }); + } + } + + return (<> + +
    + + + + + { + setSelectedRowItems(newSelection); + }} + isRowSelectable={(params) => { + return (params.row.paymentMethod != "online" && params.row.status == "confirmed") + }} + columns={columns} + customPageSize={10} + getRowHeight={() => 'auto'} + onRowDoubleClick={handleRowDoubleClick} + doLoad={React.useMemo(() => ({ + url: GET_PUBLIC_NOTICE_OFFLINE_PAYMENT_LIST, + params: _searchCriteria, + callback: function (responseData) { + setRows(responseData?.records); + } + }), [_searchCriteria])} + /> +
    +
    + setIsConfirmPopUp(false)} + PaperProps={{ + sx: { + minWidth: '40vw', + maxWidth: { xs: '90vw', s: '90vw', m: '70vw', lg: '30vw' }, + maxHeight: { xs: '90vh', s: '70vh', m: '70vh', lg: '50vh' } + } + }} + > + + + + + + + + Please Confirm to mark selected application as Paid. + + + + + + + + +
    +
    + setIsWarningPopUp(false)} + PaperProps={{ + sx: { + minWidth: '40vw', + maxWidth: { xs: '90vw', s: '90vw', m: '70vw', lg: '70vw' }, + maxHeight: { xs: '90vh', s: '70vh', m: '70vh', lg: '60vh' } + } + }} + > + Warning + + {intl.formatMessage({ id: "MSG.plzSelectApp" })} + + + + + +
    + + + ); +} diff --git a/src/pages/PublicNotice/Search_Mark_As_Paid_GLD/SearchForm.js b/src/pages/PublicNotice/Search_Mark_As_Paid_GLD/SearchForm.js new file mode 100644 index 0000000..fd08bf6 --- /dev/null +++ b/src/pages/PublicNotice/Search_Mark_As_Paid_GLD/SearchForm.js @@ -0,0 +1,389 @@ +// material-ui +import { + Button, + Grid, TextField, + Autocomplete, + Typography +} from '@mui/material'; +import MainCard from "components/MainCard"; +import { useForm } from "react-hook-form"; +import * as React from "react"; +import * as ComboData from "utils/ComboData"; +import * as DateUtils from "utils/DateUtils"; +import * as FormatUtils from "utils/FormatUtils"; +import { ThemeProvider } from "@emotion/react"; +import { PNSPS_BUTTON_THEME } from "../../../themes/buttonConst"; +import { useIntl } from "react-intl"; + +import {DatePicker} from "@mui/x-date-pickers/DatePicker"; +import dayjs from "dayjs"; +import {DemoItem} from "@mui/x-date-pickers/internals/demo"; +import {LocalizationProvider} from "@mui/x-date-pickers/LocalizationProvider"; +import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs"; +// ==============================|| DASHBOARD - DEFAULT ||============================== // +const SearchPublicNoticeForm = ({ applySearch, orgComboData, searchCriteria, issueComboData +}) => { + + const [type, setType] = React.useState([]); + // const [status, setStatus] = React.useState({ key: 0, label: 'All', type: 'all' }); + const [orgSelected, setOrgSelected] = React.useState({}); + const [orgCombo, setOrgCombo] = React.useState(); + const [issueSelected, setIssueSelected] = React.useState({}); + const [issueCombo, setIssueCombo] = React.useState([]); + const [selectedStatus, setSelectedStatus] = React.useState({key: 0, label: 'All', type: 'all'}); + + const [minDate, setMinDate] = React.useState(searchCriteria.dateFrom); + const [maxDate, setMaxDate] = React.useState(searchCriteria.dateTo); + const [fromDateValue, setFromDateValue] = React.useState("dd / mm / yyyy"); + const [toDateValue, setToDateValue] = React.useState("dd / mm / yyyy"); + + React.useEffect(() => { + setFromDateValue(minDate); + }, [minDate]); + + React.useEffect(() => { + setToDateValue(maxDate); + }, [maxDate]); + + const intl = useIntl(); + const { locale } = intl; + + const marginBottom = 2.5; + const { reset, register, handleSubmit } = useForm() + const onSubmit = (data) => { + data.status = selectedStatus?.type + let typeArray = []; + let sentDateFrom = ""; + let sentDateTo = ""; + + for (let i = 0; i < type.length; i++) { + typeArray.push(type[i].label); + } + + if (fromDateValue != "dd / mm / yyyy" && toDateValue != "dd / mm / yyyy") { + sentDateFrom = DateUtils.dateValue(fromDateValue) + sentDateTo = DateUtils.dateValue(toDateValue) + } + + const temp = { + appNo: data.appNo, + dateFrom: sentDateFrom, + dateTo: sentDateTo, + contact: data.contact, + status: (data.status === '' || data.status?.includes("all")) ? "" : data.status, + orgId: (orgSelected?.key && orgSelected?.key > 0) ? orgSelected?.key : "", + issueId: issueSelected?.id, + groupNo: data.groupNo, + }; + applySearch(temp); + }; + + React.useEffect(() => { + if (orgComboData && orgComboData.length > 0) { + setOrgCombo(orgComboData); + } + }, [orgComboData]); + + React.useEffect(() => { + if (issueComboData && issueComboData.length > 0) { + setIssueCombo(issueComboData); + } + }, [issueComboData]); + + function resetForm() { + setType([]); + // setStatus({ key: 0, label: 'All', type: 'all' }); + setOrgSelected({}); + setIssueSelected({}); + setSelectedStatus({key: 0, label: 'All', type: 'all'}); + setMinDate(DateUtils.dateValue(new Date().setDate(new Date().getDate()-14))) + setMaxDate(DateUtils.dateValue(new Date())) + reset(); + } + + const getIssueLabel=(data)=> { + let issueYear = data.issueYear + let volume = data.volume; + let issueNo = data.issueNo; + let issueDate = data.issueDate; + if (locale === 'zh-HK') { + return issueYear + + " 第" + volume + "卷," + + " 第" + issueNo + "期," + + " " + DateUtils.dateFormat(issueDate, "YYYY年MM月DD日") + + " (" + DateUtils.getWeekdayStr_ZH(issueDate) + ")"; + } else if (locale === 'zh-CN') { + return issueYear + + " 第" + volume + "卷," + + " 第" + issueNo + "期," + + " " + DateUtils.dateFormat(issueDate, "YYYY年MM月DD日") + + " (" + DateUtils.getWeekdayStr_CN(issueDate) + ")"; + } + return issueYear + + " Vol. " + FormatUtils.zeroPad(volume, 3) + + ", No. " + FormatUtils.zeroPad(issueNo, 2) + + ", " + DateUtils.dateFormat(issueDate, "D MMM YYYY (ddd)"); + } + + return ( + + +
    + + {/*row 1*/} + + + Search + + + {/*row 2*/} + + + + + + + + + + + setReceiptFromError(newError)} + slotProps={{ + field: { readOnly: true, }, + // textField: { + // helperText: receiptFromErrorMessage, + // }, + }} + format="DD/MM/YYYY" + label={"Submit Date (From)"} + value={minDate === null ? null : dayjs(minDate)} + maxDate={maxDate === null ? null : dayjs(maxDate)} + onChange={(newValue) => { + // console.log(newValue) + if(newValue!=null){ + setMinDate(newValue); + } + }} + /> + + + + + + + + setReceiptFromError(newError)} + slotProps={{ + field: { readOnly: true, }, + // textField: { + // helperText: receiptFromErrorMessage, + // }, + }} + format="DD/MM/YYYY" + label={"Submit Date (To)"} + value={maxDate === null ? null : dayjs(maxDate)} + minDate={minDate === null ? null : dayjs(minDate)} + onChange={(newValue) => { + // console.log(newValue) + if(newValue!=null){ + setMaxDate(newValue); + } + }} + /> + + + + + + + + + + + + + { + if(newValue==null){ + setSelectedStatus(ComboData.publicNoticeStatic_GLD[0]); + }else{ + setSelectedStatus(newValue); + } + }} + getOptionLabel={(option) => option.label} + renderInput={(params) => ( + + )} + /> + {/* { + const findAllIndex = newValue.findIndex((ele) => { + return ele.type === "all" + }) + + if (findAllIndex > -1) { + setSelectedStatus([newValue[findAllIndex]]); + setSelectedLabelsString('all') + } else { + const selectedLabels = newValue.map(option => option.type); + const selectedLabelsString = `${selectedLabels.join(',')}`; + setSelectedStatus(newValue); + setSelectedLabelsString(selectedLabelsString); + } + }} + getOptionLabel={(option) => option.label} + renderInput={(params) => ( + + )} + /> */} + + + { + orgCombo ? + + option.name? option.name : ""} + inputValue={orgSelected ? orgSelected.name : ""} + onChange={(event, newValue) => { + if (newValue !== null) { + setOrgSelected(newValue); + }else{ + setOrgSelected({}); + } + }} + renderInput={(params) => ( + + )} + /> + + : <> + } + + + getIssueLabel(option)} + onChange={(event, newValue) => { + setIssueSelected(newValue); + }} + renderInput={(params) => ( + + )} + /> + + + + + + + + {/*last row*/} + + + + + + + + + + + + +
    +
    + ); +}; + +export default SearchPublicNoticeForm; diff --git a/src/pages/PublicNotice/Search_Mark_As_Paid_GLD/index.js b/src/pages/PublicNotice/Search_Mark_As_Paid_GLD/index.js new file mode 100644 index 0000000..ad00847 --- /dev/null +++ b/src/pages/PublicNotice/Search_Mark_As_Paid_GLD/index.js @@ -0,0 +1,113 @@ +// material-ui +import { + Grid, + Typography, + Stack +} from '@mui/material'; +import MainCard from "components/MainCard"; +import * as React from "react"; +import * as UrlUtils from "utils/ApiPathConst"; +import * as HttpUtils from "utils/HttpUtils"; +import * as DateUtils from "utils/DateUtils"; + +import Loadable from 'components/Loadable'; +const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent'))); +const SearchForm = Loadable(React.lazy(() => import('./SearchForm'))); +const EventTable = Loadable(React.lazy(() => import('./DataGrid'))); +import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png' + +const BackgroundHead = { + backgroundImage: `url(${titleBackgroundImg})`, + width: '100%', + height: '100%', + backgroundSize: 'contain', + backgroundRepeat: 'no-repeat', + backgroundColor: '#0C489E', + backgroundPosition: 'right' +} + +// ==============================|| DASHBOARD - DEFAULT ||============================== // + +const UserSearchPage_Individual = () => { + const [orgCombo, setOrgCombo] = React.useState([]); + const [issueCombo, setIssueCombo] = React.useState([]); + const [searchCriteria, setSearchCriteria] = React.useState({ + dateTo: DateUtils.dateValue(new Date()), + dateFrom: DateUtils.dateValue(new Date().setDate(new Date().getDate() - 14)) + }); + const [onReady, setOnReady] = React.useState(false); + + React.useEffect(() => { + getOrgCombo(); + getIssueCombo(); + }, []); + + React.useEffect(() => { + setOnReady(true); + }, [searchCriteria]); + + function getOrgCombo() { + HttpUtils.get({ + url: UrlUtils.GET_ORG_COMBO, + onSuccess: function (responseData) { + let combo = responseData; + setOrgCombo(combo); + } + }); + } + + function getIssueCombo() { + HttpUtils.get({ + url: UrlUtils.GET_ISSUE_COMBO, + onSuccess: function (responseData) { + let combo = responseData; + setIssueCombo(combo); + } + }); + } + + function applySearch(input) { + setSearchCriteria(input); + } + + return ( + !onReady ? + + + + + + : + + +
    + + Mark Payment + +
    +
    + {/*row 1*/} + + + + {/*row 2*/} + + + + + +
    + ); +} +export default UserSearchPage_Individual; diff --git a/src/routes/GLDUserRoutes.js b/src/routes/GLDUserRoutes.js index 53dcfc7..725f817 100644 --- a/src/routes/GLDUserRoutes.js +++ b/src/routes/GLDUserRoutes.js @@ -10,6 +10,7 @@ import {isGranted, isGrantedAny} from "auth/utils"; const DashboardDefault = Loadable(lazy(() => import('pages/Dashboard/GLD'))); const ApplicationDetail = Loadable(lazy(() => import('pages/PublicNotice/Details_GLD'))); const ApplicationSearch = Loadable(lazy(() => import('pages/PublicNotice/Search_GLD'))); +const ApplicationMarkAsPaidSearch = Loadable(lazy(() => import('pages/PublicNotice/Search_Mark_As_Paid_GLD'))); const ProofSearch = Loadable(lazy(() => import('pages/Proof/Search_GLD'))); const ProofCreate_FromApp = Loadable(lazy(() => import('pages/Proof/Create_FromApp'))); const ProofReply_GLD = Loadable(lazy(() => import('pages/Proof/Reply_GLD'))); @@ -56,6 +57,12 @@ const GLDUserRoutes = { path: '/application/search', element: }, + + isGranted(["MAINTAIN_PAYMENT"])? + { + path: '/application/markAsPaid/search', + element: + }:{}, isGrantedAny(["VIEW_PROOF","MAINTAIN_PROOF"])?{ path: '/proof/search', diff --git a/src/utils/ApiPathConst.js b/src/utils/ApiPathConst.js index 8531d3a..42fc32c 100644 --- a/src/utils/ApiPathConst.js +++ b/src/utils/ApiPathConst.js @@ -108,6 +108,9 @@ export const GET_PUBLIC_NOTICE_getApplyUser = apiPath+'/application/get-apply-us export const POST_PUBLIC_NOTICE_APPLY = apiPath+'/application/apply'; export const POST_CHECK_APP_EXPRITY_DATE = apiPath+'/application/checkExprityDate'; +export const GET_PUBLIC_NOTICE_OFFLINE_PAYMENT_LIST = apiPath+'/application/list-Mask-As-Paid'; +export const SET_PUBLIC_NOTICE_STATUS_MARK_AS_PAID = apiPath+'/application/application-detail-status-Mark-As-Paid'; + //GLD User export const POST_ADMIN_USER_REGISTER = apiPath+'/user/registry'; export const DELETE_USER = apiPath+'/user'; @@ -124,6 +127,7 @@ export const SET_PUBLIC_NOTICE_STATUS_WITHDRAW = apiPath+'/application/applicati export const SET_PUBLIC_NOTICE_STATUS_RESUBMIT = apiPath+'/application/application-detail-status-resubmit'; export const SET_PUBLIC_NOTICE_STATUS_REVIEWED = apiPath+'/application/application-detail-status-reviewed'; export const SET_PUBLIC_NOTICE_STATUS_PUBLISH = apiPath+'/application/application-detail-status-publish'; +export const SET_PUBLIC_NOTICE_STATUS_REVOKE = apiPath+'/application/application-detail-status-Revoke-Payment'; export const SET_PUBLIC_NOTICE_STATUS_PUBLISH_BULK = apiPath+'/application/application-detail-status-publish-bulk'; export const UPDATE_PUBLIC_NOTICE_APPLY_DETAIL = apiPath+'/application/save'; export const GET_AUDIT_LOG_LIST = apiPath+'/settings/auditLogList';