From 1e721095be18b4e9f4c216c688a336d54ec17208 Mon Sep 17 00:00:00 2001 From: Alex Cheung Date: Fri, 19 Sep 2025 02:48:59 +0800 Subject: [PATCH] update import offline and xml --- src/components/FiDataGrid.js | 107 ++++++++++++------- src/pages/GFMIS/SearchForm.js | 46 ++++++-- src/pages/GFMIS/TransactionDataGrid.js | 118 +++++++++++++++++++++ src/pages/GFMIS/index.js | 24 ++++- src/pages/Payment/Search_GLD/DataGrid.js | 9 ++ src/pages/Report/FullListForm.js | 1 + src/pages/Report/SummaryForm.js | 51 ++++++++- src/pages/Report/index.js | 1 + src/pages/Setting/DrImport/index.js | 127 +++++++++++++++++------ src/utils/ApiPathConst.js | 2 + 10 files changed, 408 insertions(+), 78 deletions(-) create mode 100644 src/pages/GFMIS/TransactionDataGrid.js diff --git a/src/components/FiDataGrid.js b/src/components/FiDataGrid.js index 4640e54..cf8aba6 100644 --- a/src/components/FiDataGrid.js +++ b/src/components/FiDataGrid.js @@ -1,5 +1,6 @@ // material-ui import { useState, useEffect } from 'react'; +import { Box } from "@mui/material"; import { DataGrid, GridOverlay, } from "@mui/x-data-grid"; @@ -10,10 +11,10 @@ import { getSearchCriteria, checkSearchCriteriaPath } from "auth/utils"; // ==============================|| EVENT TABLE ||============================== // -export function FiDataGrid({ rows, columns, sx, autoHeight, +export function FiDataGrid({ rows, columns, sx, autoHeight = true, hideFooterSelectedRowCount, rowModesModel, editMode, pageSizeOptions, filterItems, customPageSize, doLoad, applyGridOnReady, applySearch, - tab, ...props }) { + tab, height, maxHeight, pagination = true, ...props }) { const intl = useIntl(); const [_rows, set_rows] = useState([]); const [_doLoad, set_doLoad] = useState({}); @@ -26,7 +27,7 @@ export function FiDataGrid({ rows, columns, sx, autoHeight, const [page, setPage] = useState(0); const [pageSize, setPageSize] = useState(10); - const [_autoHeight, set_autoHeight] = useState(true); + // const [_autoHeight, set_autoHeight] = useState(true); const [myHideFooterSelectedRowCount, setMyHideFooterSelectedRowCount] = useState(true); const [_sx, set_sx] = useState({ padding: "4 2 4 2", @@ -50,6 +51,15 @@ export function FiDataGrid({ rows, columns, sx, autoHeight, }, }); + const effectiveAutoHeight = autoHeight && !height && !maxHeight; + + const containerSx = { + width: '100%', + ...(height ? { height } : {}), + ...(maxHeight ? { maxHeight, height: '100%' } : {}), + overflow: 'hidden', + }; + const [rowCount, setRowCount] = useState(0); useEffect(() => { @@ -97,9 +107,9 @@ export function FiDataGrid({ rows, columns, sx, autoHeight, if (pageSizeOptions) { set_pageSizeOptions(pageSizeOptions) } - if (autoHeight !== undefined) { - set_autoHeight(autoHeight) - } + // if (autoHeight !== undefined) { + // set_autoHeight(autoHeight) + // } if (editMode) { set_editMode(editMode); } @@ -188,39 +198,58 @@ export function FiDataGrid({ rows, columns, sx, autoHeight, return ( - ( - - `${(_rows?.length ? page * pageSize + 1 : 0)}-${page * pageSize + (_rows?.length ?? 0)} ${intl.formatMessage({ id: "of" })} ${rowCount}` + + ( + + `${(_rows?.length ? page * pageSize + 1 : 0)}-${page * pageSize + (_rows?.length ?? 0)} ${intl.formatMessage({ id: "of" })} ${rowCount}` + } + labelRowsPerPage={intl.formatMessage({ id: "rowsPerPage" }) + ":"} + onPageChange={handleChangePage} + onRowsPerPageChange={handleChangePageSize} + /> + ), } - labelRowsPerPage={intl.formatMessage({ id: "rowsPerPage" }) + ":"} - onPageChange={handleChangePage} - onRowsPerPageChange={handleChangePageSize} - /> - ), - }} - /> + : {}), + }} + /> + + ); } diff --git a/src/pages/GFMIS/SearchForm.js b/src/pages/GFMIS/SearchForm.js index 83fe25b..ebd9401 100644 --- a/src/pages/GFMIS/SearchForm.js +++ b/src/pages/GFMIS/SearchForm.js @@ -2,8 +2,8 @@ import { Button, Grid, - // TextField, - // Autocomplete, + TextField, + Autocomplete, Typography } from '@mui/material'; import MainCard from "components/MainCard"; @@ -14,6 +14,7 @@ import {PNSPS_BUTTON_THEME} from "../../themes/buttonConst"; import {ThemeProvider} from "@emotion/react"; // import * as ComboData from "utils/ComboData"; import * as DateUtils from "utils/DateUtils"; +import * as ComboData from "utils/ComboData"; import {DatePicker} from "@mui/x-date-pickers/DatePicker"; import dayjs from "dayjs"; @@ -21,17 +22,19 @@ 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, generateXML, searchCriteria, onGridReady }) => { +const SearchPublicNoticeForm = ({ applySearch, generateXML, searchCriteria, onGridReady,selectedIds=[] }) => { // const [minDate, setMinDate] = React.useState(searchCriteria.dateFrom); const [minDate, setMinDate] = React.useState(searchCriteria.dateFrom); const [maxDate,setMaxDate] = React.useState(searchCriteria.dateFrom); const [fromDateValue, setFromDateValue] = React.useState("dd / mm / yyyy"); const [toDateValue, setToDateValue] = React.useState("dd / mm / yyyy"); + const [payMethod, setPayMethod] = React.useState(ComboData.payMethod[0]); // const [status, setStatus] = React.useState(ComboData.paymentStatus[0]); + const marginBottom = 2.5; const { - // register, + register, handleSubmit, } = useForm() @@ -59,6 +62,8 @@ const SearchPublicNoticeForm = ({ applySearch, generateXML, searchCriteria, onGr // transNo: data.transNo, dateFrom: sentDateFrom, dateTo: sentDateTo, + paymentId: selectedIds.join(','), + payMethod : (payMethod?.type && payMethod?.type != 'all') ? payMethod?.type : "", // status : (status?.type && status?.type != 'all') ? status?.type : "", }; applySearch(temp); @@ -103,7 +108,7 @@ const SearchPublicNoticeForm = ({ applySearch, generateXML, searchCriteria, onGr {/*row 2*/} - + - + + + options} + options={ComboData.payMethod} + value={payMethod} + getOptionLabel={(option) => option.label} + inputValue={payMethod?.label ? payMethod?.label : ""} + onChange={(event, newValue) => { + if(newValue==null){ + setPayMethod(ComboData.payMethod[0]); + }else{ + setPayMethod(newValue); + } + }} + renderInput={(params) => ( + + )} + InputLabelProps={{ + shrink: true + }} + /> + + {/* */} diff --git a/src/pages/GFMIS/TransactionDataGrid.js b/src/pages/GFMIS/TransactionDataGrid.js new file mode 100644 index 0000000..8bd88ca --- /dev/null +++ b/src/pages/GFMIS/TransactionDataGrid.js @@ -0,0 +1,118 @@ +// material-ui +import * as React from 'react'; +import * as DateUtils from "utils/DateUtils"; +import {PAYMENT_GFMIS_LIST} from "utils/ApiPathConst"; +// import * as HttpUtils from "utils/HttpUtils"; +import * as FormatUtils from "utils/FormatUtils" +// import { useNavigate } from "react-router-dom"; +import { FiDataGrid } from "components/FiDataGrid"; +import { clickableLink } from 'utils/CommonFunction'; +import { + // Checkbox, + // Dialog, DialogTitle, DialogContent, DialogActions, + // Button,Typography + // MenuItem +} from '@mui/material'; +// ==============================|| EVENT TABLE ||============================== // + +export default function SearchPaymentTable({ searchCriteria, applyGridOnReady, applySearch, selectedIds = [], onSelectionChange,}) { + const [_searchCriteria, set_searchCriteria] = React.useState(searchCriteria); + // const navigate = useNavigate() + + const _sx = { + padding: "4 2 4 2", + boxShadow: 1, + border: 1, + borderColor: '#DDD', + '& .MuiDataGrid-cell': { + borderTop: 1, + borderBottom: 1, + borderColor: "#EEE" + }, + '& .MuiDataGrid-footerContainer': { + border: 1, + borderColor: "#EEE" + } + } + + React.useEffect(() => { + set_searchCriteria(searchCriteria); + }, [searchCriteria]); + + const columns = [ + { + id: 'appNos', + field: 'appNos', + headerName: 'Application No.', + flex: 1, + minWidth: 150, + renderCell: (params) => { + let appNo = params.row.appNos; + return
{appNo}
+ }, + }, + { + field: 'actions', + headerName: 'Transaction No.', + flex: 1, + minWidth: 200, + cellClassName: 'actions', + renderCell: (params) => { + return clickableLink('/paymentPage/details/' + params.row.id, params.row.transNo); + }, + }, + { + id: 'transDateTime', + field: 'transDateTime', + headerName: 'Transaction Date', + flex: 1, + minWidth: 150, + valueGetter: (params) => { + return DateUtils.dateStr(params?.value); + } + }, + { + field: 'payMethod', + headerName: 'Payment Method', + flex: 1, + width: 150, + renderCell: (params) => { + return params?.value + } + }, + { + id: 'payAmount', + field: 'payAmount', + headerName: 'Amount ($)', + width: 150, + valueGetter: (params) => { + return (params?.value) ? "$ " + FormatUtils.currencyFormat(params?.value) : ""; + } + }, + ]; + + return ( +
+ onSelectionChange?.(ids)} + + doLoad={React.useMemo(() => ({ + url: PAYMENT_GFMIS_LIST, + params: _searchCriteria, + }), [_searchCriteria])} + /> +
+ ); +} diff --git a/src/pages/GFMIS/index.js b/src/pages/GFMIS/index.js index 73977a6..8d97f08 100644 --- a/src/pages/GFMIS/index.js +++ b/src/pages/GFMIS/index.js @@ -22,6 +22,7 @@ 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'))); +const TransactionTable = Loadable(React.lazy(() => import('./TransactionDataGrid'))); import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png' const BackgroundHead = { @@ -46,7 +47,7 @@ const Index = () => { const [onGridReady, setGridOnReady] = React.useState(false); const [isPopUp, setIsPopUp] = React.useState(false); const [downloadInput, setDownloadInput] = React.useState(); - + const [selectedIds, setSelectedIds] = React.useState([]); const [inputDate, setInputDate] = React.useState(searchCriteria.dateTo); const [inputDateValue, setInputDateValue] = React.useState("dd / mm / yyyy"); @@ -61,7 +62,7 @@ const Index = () => { function downloadXML() { - // console.log(input) + console.log(selectedIds.join(',')) setIsPopUp(false) let sentDateFrom = ""; @@ -73,7 +74,8 @@ const Index = () => { params:{ dateTo: downloadInput.dateTo, dateFrom: downloadInput.dateFrom, - inputDate: sentDateFrom + inputDate: sentDateFrom, + paymentId: selectedIds.join(',') }, onSuccess: (responseData) => { // console.log(responseData) @@ -158,9 +160,25 @@ const Index = () => { generateXML={generateXML} searchCriteria={searchCriteria} onGridReady={onGridReady} + selectedIds={selectedIds} />
{/*row 2*/} + + + + + { + return params?.value + } + }, { id: 'transDateTime', field: 'transDateTime', diff --git a/src/pages/Report/FullListForm.js b/src/pages/Report/FullListForm.js index bd75539..cc39182 100644 --- a/src/pages/Report/FullListForm.js +++ b/src/pages/Report/FullListForm.js @@ -90,6 +90,7 @@ const FullListForm = ({ searchCriteria, issueComboData}) => { function resetForm() { setMinDate(DateUtils.dateValue(new Date().setDate(new Date().getDate()-14))) setMaxDate(DateUtils.dateValue(new Date())) + setIssueSelected({}); reset({contact:""}); } diff --git a/src/pages/Report/SummaryForm.js b/src/pages/Report/SummaryForm.js index 78fc601..73ba3b9 100644 --- a/src/pages/Report/SummaryForm.js +++ b/src/pages/Report/SummaryForm.js @@ -3,6 +3,7 @@ import { Button, Grid, TextField, + Autocomplete, Typography } from '@mui/material'; import MainCard from "components/MainCard"; @@ -13,6 +14,7 @@ import {ThemeProvider} from "@emotion/react"; import {PNSPS_BUTTON_THEME} from "../../themes/buttonConst"; import * as HttpUtils from "utils/HttpUtils"; import * as UrlUtils from "utils/ApiPathConst"; +import * as FormatUtils from "utils/FormatUtils"; import {DatePicker} from "@mui/x-date-pickers/DatePicker"; import dayjs from "dayjs"; @@ -21,7 +23,7 @@ import {LocalizationProvider} from "@mui/x-date-pickers/LocalizationProvider"; import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs"; // ==============================|| DASHBOARD - DEFAULT ||============================== // -const SummaryForm = ({ searchCriteria}) => { +const SummaryForm = ({ searchCriteria, issueComboData}) => { const [minDate, setMinDate] = React.useState(searchCriteria.dateFrom); const [maxDate, setMaxDate] = React.useState(searchCriteria.dateTo); @@ -29,6 +31,8 @@ const SummaryForm = ({ searchCriteria}) => { const [fromDateValue, setFromDateValue] = React.useState("dd / mm / yyyy"); const [toDateValue, setToDateValue] = React.useState("dd / mm / yyyy"); + const [issueSelected, setIssueSelected] = React.useState({}); + const [issueCombo, setIssueCombo] = React.useState([]); const [waitDownload, setWaitDownload] = React.useState(false); @@ -55,6 +59,7 @@ const SummaryForm = ({ searchCriteria}) => { dateFrom: sentDateFrom, dateTo: sentDateTo, contact: data.contact, + issueId: issueSelected?.id }; doExport(temp); }; @@ -69,9 +74,30 @@ const SummaryForm = ({ searchCriteria}) => { }); }; + React.useEffect(() => { + if (issueComboData && issueComboData.length > 0) { + setIssueCombo(issueComboData); + if(searchCriteria.issueId!=undefined){ + setIssueSelected(issueComboData.find(item => item.id === searchCriteria.issueId)) + } + } + }, [issueComboData]); + + const getIssueLabel=(data)=> { + let issueYear = data.issueYear + let volume = data.volume; + let issueNo = data.issueNo; + let issueDate = data.issueDate; + return issueYear + + " Vol. " + FormatUtils.zeroPad(volume, 3) + + ", No. " + FormatUtils.zeroPad(issueNo, 2) + + ", " + DateUtils.dateFormat(issueDate, "D MMM YYYY (ddd)"); + } + function resetForm() { setMinDate(DateUtils.dateValue(new Date().setDate(new Date().getDate()-14))) setMaxDate(DateUtils.dateValue(new Date())) + setIssueSelected({}); reset({contact:""}); } @@ -106,6 +132,29 @@ const SummaryForm = ({ searchCriteria}) => { /> + + getIssueLabel(option)} + onChange={(event, newValue) => { + setIssueSelected(newValue); + }} + renderInput={(params) => ( + + )} + /> + diff --git a/src/pages/Report/index.js b/src/pages/Report/index.js index 1c3fa7d..a223ed9 100644 --- a/src/pages/Report/index.js +++ b/src/pages/Report/index.js @@ -89,6 +89,7 @@ const ReportSearchPage = () => { {/*row 2*/} diff --git a/src/pages/Setting/DrImport/index.js b/src/pages/Setting/DrImport/index.js index c2879a1..500a39f 100644 --- a/src/pages/Setting/DrImport/index.js +++ b/src/pages/Setting/DrImport/index.js @@ -73,6 +73,43 @@ const Index = () => { } document.getElementById("uploadFileBtn").value = ""; } + + const readOfflineFile = (event) => { + let file = event.target.files[0]; + setWait(true); + if (file) { + + if (file.name.toLowerCase().substr(file.name.length - 5).includes(".xlsx") + ) { + HttpUtils.postWithFiles({ + url: UrlUtils.OFFLINE_IMPORT, + params:null, + files: [event.target.files[0]], + onSuccess: function (responData) { + setWait(false); + if(responData?.msg){ + setResultStr(<>{DateUtils.datetimeStr(new Date())}
Error
{responData?.msg}) + }else if(responData?.success){ + setResultStr(<>{DateUtils.datetimeStr(new Date())}
Success
Record Count: {responData.recordCount}) + } + }, + onError: function(){ + setWait(false); + setResultStr(<>{DateUtils.datetimeStr(new Date())}
Error
Action Fail: Please import valid file.) + } + }); + } else { + setWait(false); + setWarningText("Please upload a valid file (file format: .xlsx)"); + setIsWarningPopUp(true); + document.getElementById("uploadOfflineFileBtn").value = ""; + return; + } + }else{ + setWait(false); + } + document.getElementById("uploadOfflineFileBtn").value = ""; + } return ( @@ -103,39 +140,71 @@ const Index = () => { } }); }} - >Export DR Excel - - - - { - readFile(event) - }} - /> - + >Export DR Excel + + + + + { + readFile(event) + }} + /> - - - - - - + + + + + + - + + + + + { + readOfflineFile(event) + }} + /> + + + + + + + + + + + + diff --git a/src/utils/ApiPathConst.js b/src/utils/ApiPathConst.js index 67a4acd..5008030 100644 --- a/src/utils/ApiPathConst.js +++ b/src/utils/ApiPathConst.js @@ -83,6 +83,7 @@ export const GET_FILE_DELETE = apiPath+'/file/delete'; export const DR_EXPORT = apiPath+'/settings/dr/export'; export const DR_IMPORT = apiPath+'/settings/dr/import'; +export const OFFLINE_IMPORT = apiPath+'/settings/dr/importOffline'; export const AUDIT_LOG_EXPORT = apiPath+'/settings/auditLog-export'; @@ -176,6 +177,7 @@ export const PAYMENT_LOAD = apiPath+'/payment/load';//GET export const PAYMENT_APP_LIST = apiPath+'/payment/applist';//POST export const PAYMENT_CHECK = apiPath+'/payment/check-payment';//GET export const PAYMENT_BIB = apiPath+'/payment/set-bib';//POST +export const PAYMENT_GFMIS_LIST = apiPath+'/payment/listGFMIS';//GET export const PAYMENT_LIMIT_SETTING_LIST = apiPath+'/settings/payment';//GET // export const PAYMENT_AVAILABLE_PAYMENT = paymentPath+'/api/payment/availability';//POST