From c69190d03150603a58982d901ae60a5a6039a0e2 Mon Sep 17 00:00:00 2001 From: sniedzielski Date: Fri, 9 Aug 2024 14:15:10 +0200 Subject: [PATCH 1/2] CM-992: added possibility to generate report for payroll with list of invoices --- src/actions.js | 3 +- src/components/PayrollBenefitPrintTemplate.js | 145 ++++++++++++++++++ src/components/PayrollPrintTemplate.js | 145 ++++++++++++++++++ .../payroll/BenefitConsumptionSearcher.js | 79 +++++++--- .../BenefitConsumptionSearcherModal.js | 117 ++++++++------ src/utils/last-day-month.js | 9 ++ 6 files changed, 430 insertions(+), 68 deletions(-) create mode 100644 src/components/PayrollBenefitPrintTemplate.js create mode 100644 src/components/PayrollPrintTemplate.js create mode 100644 src/utils/last-day-month.js diff --git a/src/actions.js b/src/actions.js index 1259ccc..ea07d23 100644 --- a/src/actions.js +++ b/src/actions.js @@ -1,3 +1,4 @@ +/* eslint-disable max-len */ import { decodeId, formatGQLString, @@ -54,7 +55,7 @@ const BENEFIT_CONSUMPTION_SUMMARY_PROJECTION = () => [ ]; const BENEFIT_ATTACHMENT_PROJECTION = () => [ - 'benefit{id, status, code, dateDue, receipt, individual {firstName, lastName}, jsonExt}', + 'benefit{id, status, code, dateDue, receipt, individual {firstName, lastName}, jsonExt, type, status, amount, receipt}', 'bill{id, code, terms, amountTotal, datePayed}', ]; diff --git a/src/components/PayrollBenefitPrintTemplate.js b/src/components/PayrollBenefitPrintTemplate.js new file mode 100644 index 0000000..e148176 --- /dev/null +++ b/src/components/PayrollBenefitPrintTemplate.js @@ -0,0 +1,145 @@ +/* eslint-disable max-len */ +/* eslint-disable react/no-array-index-key */ +/* eslint-disable no-nested-ternary */ +/* eslint-disable no-undef */ +import React, { + forwardRef, +} from 'react'; + +import { Divider } from '@material-ui/core'; +import { makeStyles } from '@material-ui/styles'; + +import { + useTranslations, useModulesManager, +} from '@openimis/fe-core'; +import { MODULE_NAME } from '../constants'; + +const useStyles = makeStyles(() => ({ + topHeader: { + display: 'flex', + justifyContent: 'start', + alignItems: 'center', + width: '100%', + + '& img': { + minWidth: '250px', + maxWidth: '300px', + width: 'auto', + height: 'auto', + }, + }, + printContainer: { + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + padding: '20px', + fontWeight: '500', + }, + date: { + fontSize: '16px', + }, + detailsContainer: { + display: 'flex', + flexDirection: 'column', + padding: '12px', + width: '100%', + }, + detailRow: { + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + padding: '4px', + }, + detailName: { + fontWeight: '600', + fontSize: '16px', + textTransform: 'uppercase', + }, + detailValue: { + fontWeight: '500', + backgroundColor: '#f5f5f5', + padding: '6px', + borderRadius: '8px', + fontSize: '15px', + }, + containerPadding: { + padding: '32px', + }, + dividerMargin: { + margin: '12px 0', + }, + sectionTitle: { + fontWeight: '700', + fontSize: '18px', + textTransform: 'uppercase', + marginBottom: '12px', + }, +})); + +const PayrollBenefitPrintTemplate = forwardRef(({ benefitAttachments }, ref) => { + if (!benefitAttachments) return null; + const classes = useStyles(); + const modulesManager = useModulesManager(); + const { formatMessage } = useTranslations(modulesManager, MODULE_NAME); + + return ( +
+ {benefitAttachments.map((benefitAttachment, index) => ( +
+
+ {`Payment: ${benefitAttachment.benefit.code} - ${benefitAttachment.benefit.individual.firstName}, ${benefitAttachment.benefit.individual.lastName}`} +
+
+
{formatMessage('payroll.benefitConsumption.individual.firstName')}
+
{benefitAttachment.benefit.individual.firstName}
+
+
+
{formatMessage('payroll.benefitConsumption.individual.lastName')}
+
{benefitAttachment.benefit.individual.lastName}
+
+
+
{formatMessage('payroll.benefitConsumption.code')}
+
{benefitAttachment.benefit.code}
+
+
+
{formatMessage('payroll.benefitConsumption.dateDue')}
+
{benefitAttachment.benefit.dateDue}
+
+
+
{formatMessage('payroll.benefitConsumption.receipt')}
+
{benefitAttachment.benefit.receipt}
+
+
+
{formatMessage('payroll.benefitConsumption.amount')}
+
{benefitAttachment.benefit.amount}
+
+
+
{formatMessage('payroll.benefitConsumption.type')}
+
{benefitAttachment.benefit.type}
+
+
+
{formatMessage('payroll.benefitConsumption.status')}
+
{benefitAttachment.benefit.status}
+
+
+
{formatMessage('payroll.benefitConsumption.payedOnTime')}
+
{benefitAttachment.benefit.payedOnTime ? 'Yes' : 'No'}
+
+
+
{formatMessage('payroll.benefitConsumption.paymentDate')}
+
+ {!benefitAttachment.benefit.receipt + ? '' + : benefitAttachment?.bill?.datePayed} +
+
+ +
+ ))} +
+ ); +}); + +export default PayrollBenefitPrintTemplate; diff --git a/src/components/PayrollPrintTemplate.js b/src/components/PayrollPrintTemplate.js new file mode 100644 index 0000000..dab0179 --- /dev/null +++ b/src/components/PayrollPrintTemplate.js @@ -0,0 +1,145 @@ +/* eslint-disable max-len */ +/* eslint-disable react/no-array-index-key */ +/* eslint-disable no-nested-ternary */ +/* eslint-disable no-undef */ +import React, { + forwardRef, +} from 'react'; + +import { Divider } from '@material-ui/core'; +import { makeStyles } from '@material-ui/styles'; + +import { + useTranslations, useModulesManager, +} from '@openimis/fe-core'; +import { MODULE_NAME } from '../constants'; + +const useStyles = makeStyles(() => ({ + topHeader: { + display: 'flex', + justifyContent: 'start', + alignItems: 'center', + width: '100%', + + '& img': { + minWidth: '250px', + maxWidth: '300px', + width: 'auto', + height: 'auto', + }, + }, + printContainer: { + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + padding: '20px', + fontWeight: '500', + }, + date: { + fontSize: '16px', + }, + detailsContainer: { + display: 'flex', + flexDirection: 'column', + padding: '12px', + width: '100%', + }, + detailRow: { + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + padding: '4px', + }, + detailName: { + fontWeight: '600', + fontSize: '16px', + textTransform: 'uppercase', + }, + detailValue: { + fontWeight: '500', + backgroundColor: '#f5f5f5', + padding: '6px', + borderRadius: '8px', + fontSize: '15px', + }, + containerPadding: { + padding: '32px', + }, + dividerMargin: { + margin: '12px 0', + }, + sectionTitle: { + fontWeight: '700', + fontSize: '18px', + textTransform: 'uppercase', + marginBottom: '12px', + }, +})); + +const PayrollPrintTemplate = forwardRef(({ benefitConsumptions }, ref) => { + if (!benefitConsumptions) return null; + const classes = useStyles(); + const modulesManager = useModulesManager(); + const { formatMessage } = useTranslations(modulesManager, MODULE_NAME); + + return ( +
+ {benefitConsumptions.map((benefitConsumption, index) => ( +
+
+ {`Payment: ${benefitConsumption.code} - ${benefitConsumption.individual.firstName}, ${benefitConsumption.individual.lastName}`} +
+
+
{formatMessage('payroll.benefitConsumption.individual.firstName')}
+
{benefitConsumption.individual.firstName}
+
+
+
{formatMessage('payroll.benefitConsumption.individual.lastName')}
+
{benefitConsumption.individual.lastName}
+
+
+
{formatMessage('payroll.benefitConsumption.code')}
+
{benefitConsumption.code}
+
+
+
{formatMessage('payroll.benefitConsumption.dateDue')}
+
{benefitConsumption.dateDue}
+
+
+
{formatMessage('payroll.benefitConsumption.receipt')}
+
{benefitConsumption.receipt}
+
+
+
{formatMessage('payroll.benefitConsumption.amount')}
+
{benefitConsumption.amount}
+
+
+
{formatMessage('payroll.benefitConsumption.type')}
+
{benefitConsumption.type}
+
+
+
{formatMessage('payroll.benefitConsumption.status')}
+
{benefitConsumption.status}
+
+
+
{formatMessage('payroll.benefitConsumption.payedOnTime')}
+
{benefitConsumption.payedOnTime ? 'Yes' : 'No'}
+
+
+
{formatMessage('payroll.benefitConsumption.paymentDate')}
+
+ {!benefitConsumption.receipt + ? '' + : benefitConsumption?.benefitAttachment[0]?.bill?.datePayed} +
+
+ +
+ ))} +
+ ); +}); + +export default PayrollPrintTemplate; diff --git a/src/components/payroll/BenefitConsumptionSearcher.js b/src/components/payroll/BenefitConsumptionSearcher.js index 7893ab6..8d32bbb 100644 --- a/src/components/payroll/BenefitConsumptionSearcher.js +++ b/src/components/payroll/BenefitConsumptionSearcher.js @@ -1,7 +1,14 @@ +/* eslint-disable max-len */ +/* eslint-disable no-return-assign */ /* eslint-disable no-param-reassign */ -import React from 'react'; +import React, { useRef } from 'react'; +import { useReactToPrint } from 'react-to-print'; +import PrintIcon from '@material-ui/icons/Print'; import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; +import { + Typography, Button, +} from '@material-ui/core'; import { Searcher, useModulesManager, useTranslations, @@ -11,6 +18,7 @@ import { fetchBenefitConsumptions } from '../../actions'; import { BENEFIT_CONSUMPTION_STATUS, DEFAULT_PAGE_SIZE, ROWS_PER_PAGE_OPTIONS } from '../../constants'; import BenefitConsumptionFilter from './BenefitConsumptionFilter'; import AdditionalFieldsDialog from './dialogs/AdditionalFieldsDialog'; +import PayrollPrintTemplate from '../PayrollPrintTemplate'; function BenefitConsumptionSearcher({ fetchBenefitConsumptions, @@ -25,6 +33,11 @@ function BenefitConsumptionSearcher({ }) { const modulesManager = useModulesManager(); const { formatMessageWithValues } = useTranslations('payroll', modulesManager); + const payrollPrintTemplateRef = useRef(null); + + const handlePrint = useReactToPrint({ + documentTitle: `${payrollUuid}`, + }); const fetch = (params) => fetchBenefitConsumptions(modulesManager, params); @@ -127,28 +140,48 @@ function BenefitConsumptionSearcher({ ); return ( -
- -
+ <> +
+ +
+
+ +
+ +
+
+ ); } diff --git a/src/components/payroll/BenefitConsumptionSearcherModal.js b/src/components/payroll/BenefitConsumptionSearcherModal.js index 8d8d15a..31a4db5 100644 --- a/src/components/payroll/BenefitConsumptionSearcherModal.js +++ b/src/components/payroll/BenefitConsumptionSearcherModal.js @@ -1,9 +1,12 @@ /* eslint-disable no-param-reassign */ -import React, { useState } from 'react'; +import React, { useState, useRef } from 'react'; +import { useReactToPrint } from 'react-to-print'; +import PrintIcon from '@material-ui/icons/Print'; import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; import Button from '@material-ui/core/Button'; import Dialog from '@material-ui/core/Dialog'; +import Typography from '@material-ui/core/Typography'; import DialogActions from '@material-ui/core/DialogActions'; import DialogContent from '@material-ui/core/DialogContent'; import DialogContentText from '@material-ui/core/DialogContentText'; @@ -20,6 +23,7 @@ import BenefitConsumptionFilterModal from './BenefitConsumptionFilterModal'; import ErrorSummaryModal from './dialogs/ErrorSummaryModal'; import { mutationLabel } from '../../utils/string-utils'; import AdditionalFieldsDialog from './dialogs/AdditionalFieldsDialog'; +import PayrollBenefitPrintTemplate from '../PayrollBenefitPrintTemplate'; function BenefitConsumptionSearcherModal({ fetchBenefitAttachments, @@ -39,6 +43,11 @@ function BenefitConsumptionSearcherModal({ const [selectedBenefitAttachment, setSelectedBenefitAttachment] = useState(null); const [openConfirmDialog, setOpenConfirmDialog] = useState(false); const [benefitToDelete, setBenefitToDelete] = useState(null); + const payrollPrintTemplateRef = useRef(null); + + const handlePrint = useReactToPrint({ + documentTitle: `${payrollUuid}`, + }); const fetch = (params) => { fetchBenefitAttachments(modulesManager, params); @@ -193,54 +202,74 @@ function BenefitConsumptionSearcherModal({ ); return ( -
- - {selectedBenefitAttachment && ( + <> +
+ +
+
+ + {selectedBenefitAttachment && ( setSelectedBenefitAttachment(null)} benefitAttachment={selectedBenefitAttachment} /> - )} - setOpenConfirmDialog(false)} - > - {formatMessage('benefitConsumption.delete.confirm.title')} - - - {formatMessage('benefitConsumption.delete.confirm.message')} - - - - - - - -
+ )} + setOpenConfirmDialog(false)} + > + {formatMessage('benefitConsumption.delete.confirm.title')} + + + {formatMessage('benefitConsumption.delete.confirm.message')} + + + + + + + +
+ +
+
+ ); } diff --git a/src/utils/last-day-month.js b/src/utils/last-day-month.js new file mode 100644 index 0000000..d8516a2 --- /dev/null +++ b/src/utils/last-day-month.js @@ -0,0 +1,9 @@ +export default function getLastDayOfMonth(runMonth, runYear) { + // Create a new Date object for the first day of the next month + const nextMonthDate = new Date(runYear, runMonth, 1); + + // Subtract 1 day from the first day of the next month to get the last day of the current month + const lastDayOfMonth = new Date(nextMonthDate - 1); + + return lastDayOfMonth; +} From 3ef1bffae4abc26e7215a8a4c9ad0980cd713188 Mon Sep 17 00:00:00 2001 From: sniedzielski Date: Fri, 9 Aug 2024 14:19:19 +0200 Subject: [PATCH 2/2] CM-992: removed redundant data in report --- package.json | 4 +++- src/components/PayrollPrintTemplate.js | 4 ---- src/components/payroll/BenefitConsumptionSearcherModal.js | 1 + 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index c3ac08c..c668984 100644 --- a/package.json +++ b/package.json @@ -43,5 +43,7 @@ "files": [ "dist" ], - "dependencies": {} + "dependencies": { + "react-to-print": "^2.15.1" + } } diff --git a/src/components/PayrollPrintTemplate.js b/src/components/PayrollPrintTemplate.js index dab0179..1355f27 100644 --- a/src/components/PayrollPrintTemplate.js +++ b/src/components/PayrollPrintTemplate.js @@ -123,10 +123,6 @@ const PayrollPrintTemplate = forwardRef(({ benefitConsumptions }, ref) => {
{formatMessage('payroll.benefitConsumption.status')}
{benefitConsumption.status}
-
-
{formatMessage('payroll.benefitConsumption.payedOnTime')}
-
{benefitConsumption.payedOnTime ? 'Yes' : 'No'}
-
{formatMessage('payroll.benefitConsumption.paymentDate')}
diff --git a/src/components/payroll/BenefitConsumptionSearcherModal.js b/src/components/payroll/BenefitConsumptionSearcherModal.js index 31a4db5..623a9f2 100644 --- a/src/components/payroll/BenefitConsumptionSearcherModal.js +++ b/src/components/payroll/BenefitConsumptionSearcherModal.js @@ -1,3 +1,4 @@ +/* eslint-disable max-len */ /* eslint-disable no-param-reassign */ import React, { useState, useRef } from 'react'; import { useReactToPrint } from 'react-to-print';