Skip to content

Commit

Permalink
CM-930: added frontend improvements in terms of performance, digital …
Browse files Browse the repository at this point in the history
…payment support (#52)
  • Loading branch information
sniedzielski authored Jun 17, 2024
1 parent 28b09e6 commit 3deee25
Show file tree
Hide file tree
Showing 11 changed files with 471 additions and 21 deletions.
16 changes: 15 additions & 1 deletion src/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,20 @@ const PAYROLL_PROJECTION = (modulesManager) => [
'isDeleted',
];

const PAYROLL_SEARCHER_PROJECTION = (modulesManager) => [
'id',
'name',
'paymentMethod',
'paymentPlan { code, id, name, benefitPlan }',
`paymentPoint { ${PAYMENT_POINT_PROJECTION(modulesManager).join(' ')} }`,
'paymentCycle { code, startDate, endDate }',
'jsonExt',
'status',
'dateValidFrom',
'dateValidTo',
'isDeleted',
];

const CSV_RECONCILIATION_PROJECTION = () => [
'fileName',
'status',
Expand Down Expand Up @@ -186,7 +200,7 @@ export function updatePaymentPoint(paymentPoint, clientMutationLabel) {
}

export function fetchPayrolls(modulesManager, params) {
const payload = formatPageQueryWithCount('payroll', params, PAYROLL_PROJECTION(modulesManager));
const payload = formatPageQueryWithCount('payroll', params, PAYROLL_SEARCHER_PROJECTION(modulesManager));
return graphql(payload, ACTION_TYPE.SEARCH_PAYROLLS);
}

Expand Down
2 changes: 1 addition & 1 deletion src/components/payroll/PayrollSearcherApproved.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ function PayrollSearcherApproved({
(payroll) => (
<PaymentApproveForPaymentSummary
classes={classes}
payroll={payroll}
payrollDetail={payroll}
/>
),
];
Expand Down
159 changes: 159 additions & 0 deletions src/components/payroll/PayrollSearcherPending.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
import React, { useRef, useEffect } from 'react';
import { connect, useSelector } from 'react-redux';
import { bindActionCreators } from 'redux';

import {
Searcher,
useHistory,
useModulesManager,
useTranslations,
coreConfirm,
clearConfirm,
journalize,
} from '@openimis/fe-core';
import PayrollFilter from './PayrollFilter';
import {
DEFAULT_PAGE_SIZE, MODULE_NAME, PAYROLL_PAYROLL_ROUTE, RIGHT_PAYROLL_SEARCH, ROWS_PER_PAGE_OPTIONS, PAYROLL_STATUS,
} from '../../constants';
import { fetchPayrolls } from '../../actions';
import PayrollReconciliationFilesDialog from './dialogs/PayrollReconciliationFilesDialog';
import PayrollPendingPayrollSummary from './dialogs/PayrollPendingPayrollSummary';

function PayrollSearcherPending({
fetchingPayrolls,
fetchedPayrolls,
errorPayrolls,
payrolls,
pageInfo,
totalCount,
fetchPayrolls,
submittingMutation,
mutation,
classes,
}) {
const history = useHistory();
const modulesManager = useModulesManager();
const { formatMessageWithValues } = useTranslations(MODULE_NAME, modulesManager);
const rights = useSelector((store) => store.core.user.i_user.rights ?? []);

const prevSubmittingMutationRef = useRef();

useEffect(() => {
if (prevSubmittingMutationRef.current && !submittingMutation) {
journalize(mutation);
}
}, [submittingMutation]);

useEffect(() => {
prevSubmittingMutationRef.current = submittingMutation;
});

const headers = () => [
'payroll.name',
'payroll.paymentPlan',
'payroll.paymentPoint',
'payroll.status',
'payroll.paymentMethod',
'emptyLabel',
];

const sorts = () => [
['name', true],
['paymentPlan', true],
['paymentPoint', true],
['status', true],
['paymentMethod', true],
];

const defaultFilters = () => ({
isDeleted: {
value: false,
filter: 'isDeleted: false',
},
status: {
value: PAYROLL_STATUS.PENDING_APPROVAL,
filter: `status: ${PAYROLL_STATUS.PENDING_APPROVAL}`,
},
});

const fetch = (params) => fetchPayrolls(modulesManager, params);

const rowIdentifier = (payroll) => payroll.id;

const openPayroll = (payroll) => rights.includes(RIGHT_PAYROLL_SEARCH) && history.push(
`/${modulesManager.getRef(PAYROLL_PAYROLL_ROUTE)}/${payroll?.id}`,
);

const itemFormatters = () => [
(payroll) => payroll.name,
(payroll) => (payroll.benefitPlan
? `${payroll.benefitPlan.code} ${payroll.benefitPlan.name}` : ''),
(payroll) => (payroll.paymentPoint
? `${payroll.paymentPoint.name}` : ''),
(payroll) => (payroll.status
? `${payroll.status}` : ''),
(payroll) => (payroll.paymentMethod
? `${payroll.paymentMethod}` : ''),
(payroll) => (
<PayrollReconciliationFilesDialog
classes={classes}
payroll={payroll}
/>
),
(payroll) => (
<PayrollPendingPayrollSummary
classes={classes}
payrollDetail={payroll}
/>
),
];

const onDoubleClick = (payroll) => openPayroll(payroll);

const payrollFilter = ({ filters, onChangeFilters }) => (
<PayrollFilter filters={filters} onChangeFilters={onChangeFilters} statusReadOnly />
);

return (
<Searcher
module="payroll"
FilterPane={payrollFilter}
fetch={fetch}
items={payrolls}
itemsPageInfo={pageInfo}
fetchedItems={fetchedPayrolls}
fetchingItems={fetchingPayrolls}
errorItems={errorPayrolls}
tableTitle={formatMessageWithValues('payrollSearcher.results', { totalCount })}
headers={headers}
itemFormatters={itemFormatters}
sorts={sorts}
rowsPerPageOptions={ROWS_PER_PAGE_OPTIONS}
defaultPageSize={DEFAULT_PAGE_SIZE}
rowIdentifier={rowIdentifier}
onDoubleClick={onDoubleClick}
defaultFilters={defaultFilters()}
/>
);
}

const mapStateToProps = (state) => ({
fetchingPayrolls: state.payroll.fetchingPayrolls,
fetchedPayrolls: state.payroll.fetchedPayrolls,
errorPayrolls: state.payroll.errorPayrolls,
payrolls: state.payroll.payrolls,
pageInfo: state.payroll.payrollsPageInfo,
totalCount: state.payroll.payrollsTotalCount,
confirmed: state.core.confirmed,
submittingMutation: state.payroll.submittingMutation,
mutation: state.payroll.mutation,
});

const mapDispatchToProps = (dispatch) => bindActionCreators({
fetchPayrolls,
journalize,
clearConfirm,
coreConfirm,
}, dispatch);

export default connect(mapStateToProps, mapDispatchToProps)(PayrollSearcherPending);
2 changes: 1 addition & 1 deletion src/components/payroll/PayrollSearcherReconciled.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ function PayrollSearcherReconciled({
(payroll) => (
<PaymentReconciliationSummaryDialog
classes={classes}
payroll={payroll}
payrollDetail={payroll}
/>
),
];
Expand Down
3 changes: 2 additions & 1 deletion src/components/payroll/PayrollTab.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable max-len */
import React, { useState } from 'react';
import { Paper, Grid } from '@material-ui/core';
import {
Expand Down Expand Up @@ -90,7 +91,7 @@ function PayrollTab({
{formatMessage('payroll.summary.download')}
</Button>
)}
{payrollUuid && payroll?.status === PAYROLL_STATUS.APPROVE_FOR_PAYMENT
{payrollUuid && payroll?.status === PAYROLL_STATUS.APPROVE_FOR_PAYMENT && payroll.paymentMethod === 'StrategyOfflinePayment'
&& (
<PayrollPaymentDataUploadDialog
payrollUuid={payrollUuid}
Expand Down
32 changes: 20 additions & 12 deletions src/components/payroll/dialogs/PaymentApproveForPaymentSummary.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import Typography from '@material-ui/core/Typography';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { MODULE_NAME, BENEFIT_CONSUMPTION_STATUS } from '../../../constants';
import { closePayroll, rejectPayroll } from '../../../actions';
import { closePayroll, fetchPayroll, rejectPayroll } from '../../../actions';
import { mutationLabel } from '../../../utils/string-utils';
import BenefitConsumptionSearcherModal from '../BenefitConsumptionSearcherModal';
import downloadPayroll from '../../../utils/export';
Expand All @@ -27,26 +27,32 @@ function PaymentApproveForPaymentDialog({
payroll,
closePayroll,
rejectPayroll,
payrollDetail,
fetchPayroll,
}) {
const modulesManager = useModulesManager();
const [payrollUuid] = useState(payrollDetail?.id ?? null);
const [isOpen, setIsOpen] = useState(false);
const [totalBeneficiaries, setTotalBeneficiaries] = useState(0);
const [selectedBeneficiaries, setSelectedBeneficiaries] = useState(0);
const [totalBillAmount, setTotalBillAmount] = useState(0);
const [totalReconciledBillAmount, setTotalReconciledBillAmount] = useState(0);

const handleOpen = () => {
if (payrollUuid) {
fetchPayroll(modulesManager, [`id: "${payrollUuid}"`]);
}
setIsOpen(true);
};

const handleClose = () => {
setIsOpen(false);
};

const modulesManager = useModulesManager();
const { formatMessage, formatMessageWithValues } = useTranslations(MODULE_NAME, modulesManager);

useEffect(() => {
if (isOpen) {
if (isOpen && Object.keys(payroll).length > 0) {
// Calculate total benefits and reconciled benefits
const total = payroll.benefitConsumption.length;
const selected = payroll.benefitConsumption.filter(
Expand Down Expand Up @@ -80,16 +86,16 @@ function PaymentApproveForPaymentDialog({
const closePayrollCallback = () => {
handleClose();
closePayroll(
payroll,
formatMessageWithValues('payroll.mutation.closeLabel', mutationLabel(payroll)),
payrollDetail,
formatMessageWithValues('payroll.mutation.closeLabel', mutationLabel(payrollDetail)),
);
};

const rejectPayrollCallback = () => {
handleClose();
rejectPayroll(
payroll,
formatMessageWithValues('payroll.mutation.closeLabel', mutationLabel(payroll)),
payrollDetail,
formatMessageWithValues('payroll.mutation.closeLabel', mutationLabel(payrollDetail)),
);
};

Expand Down Expand Up @@ -126,7 +132,7 @@ function PaymentApproveForPaymentDialog({
marginTop: '10px',
}}
>
{formatMessageWithValues('payroll.reconciliationSummary', { payrollName: payroll.name })}
{formatMessageWithValues('payroll.reconciliationSummary', { payrollName: payrollDetail.name })}
</DialogTitle>
<DialogContent>
<Grid container spacing={2}>
Expand Down Expand Up @@ -164,7 +170,7 @@ function PaymentApproveForPaymentDialog({
<div
style={{ backgroundColor: '#DFEDEF' }}
>
<BenefitConsumptionSearcherModal payrollUuid={payroll.id} />
<BenefitConsumptionSearcherModal payrollUuid={payrollDetail.id} />
</div>
</DialogContent>
<DialogActions
Expand All @@ -179,7 +185,7 @@ function PaymentApproveForPaymentDialog({
<div style={{ maxWidth: '3000px' }}>
<div style={{ float: 'left' }}>
<Button
onClick={() => closePayrollCallback(payroll)}
onClick={() => closePayrollCallback(payrollDetail)}
variant="contained"
color="primary"
disabled={selectedBeneficiaries === 0}
Expand All @@ -191,7 +197,7 @@ function PaymentApproveForPaymentDialog({
{formatMessage('payroll.summary.approveAndClose')}
</Button>
<Button
onClick={() => downloadPayrollData(payroll.id, payroll.name)}
onClick={() => downloadPayrollData(payrollDetail.id, payrollDetail.name)}
variant="contained"
color="primary"
style={{
Expand All @@ -202,7 +208,7 @@ function PaymentApproveForPaymentDialog({
{formatMessage('payroll.summary.download')}
</Button>
<Button
onClick={() => rejectPayrollCallback(payroll)}
onClick={() => rejectPayrollCallback(payrollDetail)}
variant="contained"
color="primary"
style={{
Expand Down Expand Up @@ -237,11 +243,13 @@ function PaymentApproveForPaymentDialog({
const mapStateToProps = (state) => ({
rights: !!state.core && !!state.core.user && !!state.core.user.i_user ? state.core.user.i_user.rights : [],
confirmed: state.core.confirmed,
payroll: state.payroll.payroll,
});

const mapDispatchToProps = (dispatch) => bindActionCreators({
closePayroll,
rejectPayroll,
fetchPayroll,
}, dispatch);

export default connect(mapStateToProps, mapDispatchToProps)(PaymentApproveForPaymentDialog);
Loading

0 comments on commit 3deee25

Please sign in to comment.