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/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..1355f27
--- /dev/null
+++ b/src/components/PayrollPrintTemplate.js
@@ -0,0 +1,141 @@
+/* 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.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 (
-
-
-
+ <>
+
+ }
+ onClick={(e) => {
+ e.preventDefault();
+ handlePrint(null, () => payrollPrintTemplateRef.current);
+ }}
+ >
+ Print
+
+
+
+ >
);
}
diff --git a/src/components/payroll/BenefitConsumptionSearcherModal.js b/src/components/payroll/BenefitConsumptionSearcherModal.js
index 8d8d15a..623a9f2 100644
--- a/src/components/payroll/BenefitConsumptionSearcherModal.js
+++ b/src/components/payroll/BenefitConsumptionSearcherModal.js
@@ -1,9 +1,13 @@
+/* eslint-disable max-len */
/* 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 +24,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 +44,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 +203,74 @@ function BenefitConsumptionSearcherModal({
);
return (
-
-
- {selectedBenefitAttachment && (
+ <>
+
+ }
+ onClick={(e) => {
+ e.preventDefault();
+ handlePrint(null, () => payrollPrintTemplateRef.current);
+ }}
+ >
+ Print
+
+
+
+
+ {selectedBenefitAttachment && (
setSelectedBenefitAttachment(null)}
benefitAttachment={selectedBenefitAttachment}
/>
- )}
- setOpenConfirmDialog(false)}
- >
- {formatMessage('benefitConsumption.delete.confirm.title')}
-
-
- {formatMessage('benefitConsumption.delete.confirm.message')}
-
-
-
- setOpenConfirmDialog(false)} color="primary">
- {formatMessage('benefitConsumption.cancel')}
-
-
- {formatMessage('benefitConsumption.confirm')}
-
-
-
-
+ )}
+
setOpenConfirmDialog(false)}
+ >
+ {formatMessage('benefitConsumption.delete.confirm.title')}
+
+
+ {formatMessage('benefitConsumption.delete.confirm.message')}
+
+
+
+ setOpenConfirmDialog(false)} color="primary">
+ {formatMessage('benefitConsumption.cancel')}
+
+
+ {formatMessage('benefitConsumption.confirm')}
+
+
+
+
+
+ >
);
}
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;
+}