Add year selection for report; fetch report for selected year
This commit is contained in:
@@ -1,22 +1,92 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { Container, Button, Loader } from 'semantic-ui-react';
|
import { Container, Button, Loader, Input, Message, Grid } from 'semantic-ui-react';
|
||||||
|
|
||||||
import MainMenu from '../../components/MainMenu';
|
import MainMenu from '../../components/MainMenu';
|
||||||
|
|
||||||
import { fetchMemberPracticeSummaryReport } from '../../store/actions';
|
import { fetchMemberPracticeSummaryReport } from '../../store/actions';
|
||||||
|
|
||||||
class MemberPracticeSummaryReport extends Component {
|
class MemberPracticeSummaryReport extends Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
year: new Date().getFullYear(),
|
||||||
|
stateError: null,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onGenerateReportClick = () => {
|
||||||
|
const {fetchMemberPracticeSummaryReport} = this.props;
|
||||||
|
const { year } = this.state;
|
||||||
|
|
||||||
|
const currentYear = new Date().getFullYear();
|
||||||
|
const parsedYear = parseInt(year);
|
||||||
|
|
||||||
|
if (!parsedYear || isNaN(parsedYear)){
|
||||||
|
this.setState({stateError: 'Year is not a number'});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parsedYear > currentYear){
|
||||||
|
this.setState({stateError: 'Selected year cannot be greater than current year'});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchMemberPracticeSummaryReport(year);
|
||||||
|
};
|
||||||
|
|
||||||
|
onYearInputChange = (event, data) => {
|
||||||
|
let newYear = parseInt(data.value)
|
||||||
|
if (!newYear || isNaN(newYear)){
|
||||||
|
newYear = new Date().getFullYear();
|
||||||
|
}
|
||||||
|
this.setState({year: newYear, stateError: null})
|
||||||
|
};
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { fetchMemberPracticeSummaryReport, pendingReport } = this.props;
|
const { pendingReport, fetchReportError } = this.props;
|
||||||
|
const { year, stateError } = this.state;
|
||||||
|
|
||||||
|
let error;
|
||||||
|
error = stateError ? stateError : null;
|
||||||
|
error = fetchReportError ? fetchReportError : error;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<MainMenu/>
|
<MainMenu/>
|
||||||
<h3>Member Practice Summary Report</h3>
|
<h3>Member Practice Summary Report</h3>
|
||||||
<hr/>
|
<hr/>
|
||||||
<br/>
|
<br/>
|
||||||
|
<Grid stackable>
|
||||||
|
<Grid.Row>
|
||||||
|
<Grid.Column width={5}>
|
||||||
|
<Input
|
||||||
|
fluid
|
||||||
|
type="number"
|
||||||
|
label={'Report for : '}
|
||||||
|
value={year}
|
||||||
|
onChange={this.onYearInputChange}
|
||||||
|
/>
|
||||||
|
</Grid.Column>
|
||||||
|
<Grid.Column width={5}>
|
||||||
|
<Button disabled={pendingReport} onClick={this.onGenerateReportClick}>Generate Report</Button>
|
||||||
|
</Grid.Column>
|
||||||
|
</Grid.Row>
|
||||||
|
{error &&
|
||||||
|
<Grid.Row>
|
||||||
|
<Grid.Column>
|
||||||
|
<Message negative>
|
||||||
|
<Message.Header>Error</Message.Header>
|
||||||
|
<br/>
|
||||||
|
<Message.Content><p>{error}</p></Message.Content>
|
||||||
|
</Message>
|
||||||
|
</Grid.Column>
|
||||||
|
</Grid.Row>
|
||||||
|
}
|
||||||
|
</Grid>
|
||||||
<Loader active={pendingReport} />
|
<Loader active={pendingReport} />
|
||||||
<Button disabled={pendingReport} onClick={fetchMemberPracticeSummaryReport}>Generate Report</Button>
|
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -24,10 +94,11 @@ class MemberPracticeSummaryReport extends Component {
|
|||||||
|
|
||||||
const mapStateToProps = (state) => ({
|
const mapStateToProps = (state) => ({
|
||||||
pendingReport: state.memberPracticeSummaryReport.pending,
|
pendingReport: state.memberPracticeSummaryReport.pending,
|
||||||
|
fetchReportError: state.memberPracticeSummaryReport.error,
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
fetchMemberPracticeSummaryReport: () => fetchMemberPracticeSummaryReport(dispatch),
|
fetchMemberPracticeSummaryReport: (year) => fetchMemberPracticeSummaryReport(dispatch, year),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(MemberPracticeSummaryReport);
|
export default connect(mapStateToProps, mapDispatchToProps)(MemberPracticeSummaryReport);
|
||||||
|
|||||||
@@ -113,15 +113,24 @@ export const checkProcessing = (dispatch) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const fetchMemberPracticeSummaryReport = (dispatch) => {
|
export const fetchMemberPracticeSummaryReport = (dispatch, year) => {
|
||||||
dispatch({type: FETCH_MEMBER_PRACTICE_SUMMARY_REPORT_PENDING});
|
dispatch({type: FETCH_MEMBER_PRACTICE_SUMMARY_REPORT_PENDING});
|
||||||
API.get('integration/report/practiceSummary', {
|
API.get(`integration/report/practiceSummary/${year}`, {
|
||||||
responseType: 'blob',
|
responseType: 'blob',
|
||||||
})
|
})
|
||||||
.then(response => {
|
.then(response => {
|
||||||
dispatch({type: FETCH_MEMBER_PRACTICE_SUMMARY_REPORT_SUCCESS, payload: response});
|
dispatch({type: FETCH_MEMBER_PRACTICE_SUMMARY_REPORT_SUCCESS, payload: response});
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
dispatch({type: FETCH_MEMBER_PRACTICE_SUMMARY_REPORT_FAILED, payload: error.response});
|
let errorMessage = 'Error generating Member Practice Summary Report';
|
||||||
|
switch (error.response.status) {
|
||||||
|
case 400:
|
||||||
|
errorMessage = 'Year cannot be greater than current year and it has to be a number';
|
||||||
|
break;
|
||||||
|
case 500:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dispatch({type: FETCH_MEMBER_PRACTICE_SUMMARY_REPORT_FAILED, payload: errorMessage});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
const moment = require('moment-timezone');
|
||||||
|
|
||||||
const { getMappingsFromDatabase, fetchOffices, fetchResources, saveNewMappingToDatabase } = require('../services/officeRnD/resources');
|
const { getMappingsFromDatabase, fetchOffices, fetchResources, saveNewMappingToDatabase } = require('../services/officeRnD/resources');
|
||||||
const { getAllIncidents, getMemberPracticeSummaryReport } = require('../services/integration/reports');
|
const { getAllIncidents, getMemberPracticeSummaryReport } = require('../services/integration/reports');
|
||||||
const { getMembersFeesForDateRange } = require('../services/integration/invoiceIntegration');
|
const { getMembersFeesForDateRange } = require('../services/integration/invoiceIntegration');
|
||||||
@@ -7,6 +9,8 @@ const { deleteFeesFromORD, addFeesToORD } = require('../services/officeRnD/fees'
|
|||||||
const { checkBookingChanges } = require('../services/integration/checkBookingChange');
|
const { checkBookingChanges } = require('../services/integration/checkBookingChange');
|
||||||
const { checkIfProcessing } = require('../services/integration/processingStatus');
|
const { checkIfProcessing } = require('../services/integration/processingStatus');
|
||||||
|
|
||||||
|
const { UI_TIMEZONE } = require('../constants/constants');
|
||||||
|
|
||||||
const getKnownOfficeResourceMappings = (req, res) => {
|
const getKnownOfficeResourceMappings = (req, res) => {
|
||||||
const dataToFetch = [getMappingsFromDatabase(), fetchOffices(), fetchResources() ];
|
const dataToFetch = [getMappingsFromDatabase(), fetchOffices(), fetchResources() ];
|
||||||
|
|
||||||
@@ -127,7 +131,22 @@ const checkProcessingStatus = (req, res) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getPracticeSummaryReport = (req, res) => {
|
const getPracticeSummaryReport = (req, res) => {
|
||||||
getMemberPracticeSummaryReport()
|
const year = req.params.year;
|
||||||
|
|
||||||
|
const currentYear = moment.tz(UI_TIMEZONE).year();
|
||||||
|
const parsedYear = parseInt(year);
|
||||||
|
|
||||||
|
if (!parsedYear || isNaN(parsedYear)){
|
||||||
|
res.status(400).send('Year is not a number');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parsedYear > currentYear){
|
||||||
|
res.status(400).send('Selected year cannot be greater than current year');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
getMemberPracticeSummaryReport(parsedYear)
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
const pathToDownloadFile = `${__dirname}/../${result.reportPath}`;
|
const pathToDownloadFile = `${__dirname}/../${result.reportPath}`;
|
||||||
res.download(pathToDownloadFile);
|
res.download(pathToDownloadFile);
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ router.post('/integration/addFees', addFees);
|
|||||||
|
|
||||||
router.get('/integration/processing', checkProcessingStatus);
|
router.get('/integration/processing', checkProcessingStatus);
|
||||||
|
|
||||||
router.get('/integration/report/practiceSummary', getPracticeSummaryReport);
|
router.get('/integration/report/practiceSummary/:year', getPracticeSummaryReport);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -318,10 +318,8 @@ const getAllIncidents = (dateRange, memberIds) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const getMemberPracticeSummaryReport = (res) => {
|
const getMemberPracticeSummaryReport = (year) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const year = moment.tz(UI_TIMEZONE).year();
|
|
||||||
|
|
||||||
const asyncJobs = [checkBookingChanges(), getAllBookingsForYear(year), fetchAllMembers()];
|
const asyncJobs = [checkBookingChanges(), getAllBookingsForYear(year), fetchAllMembers()];
|
||||||
|
|
||||||
Promise.all(asyncJobs)
|
Promise.all(asyncJobs)
|
||||||
|
|||||||
Reference in New Issue
Block a user