fix: AR aging summary report.

This commit is contained in:
a.bouhuolia
2021-02-21 18:50:47 +02:00
parent 1aaea21f6e
commit 6e6103ca99
17 changed files with 252 additions and 272 deletions

View File

@@ -1,25 +1,19 @@
import React, { useEffect, useState, useCallback } from 'react';
import { useIntl } from 'react-intl';
import { queryCache, useQuery } from 'react-query';
import React, { useState, useCallback } from 'react';
import moment from 'moment';
import 'style/pages/FinancialStatements/ARAgingSummary.scss';
import { FinancialStatement } from 'components';
import DashboardInsider from 'components/Dashboard/DashboardInsider';
import ARAgingSummaryActionsBar from './ARAgingSummaryActionsBar';
import DashboardPageContent from 'components/Dashboard/DashboardPageContent';
import ARAgingSummaryHeader from './ARAgingSummaryHeader';
import ReceivableAgingSummaryTable from './ARAgingSummaryTable';
import ARAgingSummaryActionsBar from './ARAgingSummaryActionsBar';
import ARAgingSummaryTable from './ARAgingSummaryTable';
import DashboardPageContent from 'components/Dashboard/DashboardPageContent';
import { ARAgingSummaryProvider } from './ARAgingSummaryProvider';
import withSettings from 'containers/Settings/withSettings';
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
import withARAgingSummaryActions from './withARAgingSummaryActions';
import withARAgingSummary from './withARAgingSummary';
import { compose } from 'utils';
import { transfromFilterFormToQuery } from './common';
import 'style/pages/FinancialStatements/ARAgingSummary.scss';
/**
* AR aging summary report.
@@ -27,115 +21,55 @@ import 'style/pages/FinancialStatements/ARAgingSummary.scss';
function ReceivableAgingSummarySheet({
// #withSettings
organizationName,
// #withDashboardActions
changePageTitle,
setDashboardBackLink,
setSidebarShrink,
// #withARAgingSummaryActions
requestReceivableAgingSummary,
refreshARAgingSummary,
toggleFilterARAgingSummary,
// #withARAgingSummary
ARAgingSummaryRefresh,
}) {
const { formatMessage } = useIntl();
const [query, setQuery] = useState({
const [filter, setFilter] = useState({
asDate: moment().endOf('day').format('YYYY-MM-DD'),
agingBeforeDays: 30,
agingDaysBefore: 30,
agingPeriods: 3,
});
useEffect(() => {
changePageTitle(formatMessage({ id: 'receivable_aging_summary' }));
}, [changePageTitle, formatMessage]);
useEffect(() => {
if (ARAgingSummaryRefresh) {
queryCache.invalidateQueries('receivable-aging-summary');
refreshARAgingSummary(false);
}
}, [ARAgingSummaryRefresh, refreshARAgingSummary]);
useEffect(() => {
setSidebarShrink()
// Show the back link on dashboard topbar.
setDashboardBackLink(true);
return () => {
// Hide the back link on dashboard topbar.
setDashboardBackLink(false);
};
}, [setDashboardBackLink,setSidebarShrink]);
// Handle fetching receivable aging summary report.
const fetchARAgingSummarySheet = useQuery(
['receivable-aging-summary', query],
(key, q) =>
requestReceivableAgingSummary({
...transfromFilterFormToQuery(q),
}),
{ manual: true },
);
// Handle fetch the data of receivable aging summary sheet.
const handleFetchData = useCallback((...args) => {}, []);
// Handle filter submit.
const handleFilterSubmit = useCallback(
(filter) => {
const _filter = {
...filter,
asDate: moment(filter.asDate).format('YYYY-MM-DD'),
};
setQuery(_filter);
refreshARAgingSummary(true);
toggleFilterARAgingSummary(false);
setFilter(_filter);
},
[refreshARAgingSummary, toggleFilterARAgingSummary],
[],
);
// Handle number format submit.
const handleNumberFormatSubmit = (numberFormat) => {
setQuery({
...query,
numberFormat
});
refreshARAgingSummary(true);
setFilter({ ...filter, numberFormat });
};
return (
<DashboardInsider>
<ARAgingSummaryProvider filter={filter}>
<ARAgingSummaryActionsBar
numberFormat={query.numberFormat}
numberFormat={filter.numberFormat}
onNumberFormatSubmit={handleNumberFormatSubmit}/>
<DashboardPageContent>
<FinancialStatement>
<ARAgingSummaryHeader
pageFilter={query}
pageFilter={filter}
onSubmitFilter={handleFilterSubmit}
/>
<div class="financial-statement__body">
<ReceivableAgingSummaryTable
<ARAgingSummaryTable
organizationName={organizationName}
receivableAgingSummaryQuery={query}
onFetchData={handleFetchData}
/>
</div>
</FinancialStatement>
</DashboardPageContent>
</DashboardInsider>
</ARAgingSummaryProvider>
);
}
export default compose(
withDashboardActions,
withARAgingSummaryActions,
withSettings(({ organizationSettings }) => ({
organizationName: organizationSettings.name,
})),
withARAgingSummary(({ ARAgingSummaryRefresh }) => ({
ARAgingSummaryRefresh: ARAgingSummaryRefresh,
})),
)(ReceivableAgingSummarySheet);

View File

@@ -15,34 +15,34 @@ import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
import Icon from 'components/Icon';
import NumberFormatDropdown from 'components/NumberFormatDropdown';
import withARAgingSummary from './withARAgingSummary';
import { useARAgingSummaryContext } from './ARAgingSummaryProvider';
import withARAgingSummaryActions from './withARAgingSummaryActions';
import { compose } from 'utils';
import { safeInvoke } from '@blueprintjs/core/lib/esm/common/utils';
/**
* AR Aging summary sheet - Actions bar.
* A/R Aging summary sheet - Actions bar.
*/
function ARAgingSummaryActionsBar({
// #withReceivableAging
receivableAgingFilter,
ARAgingSummaryLoading,
// #withReceivableAgingActions
toggleFilterARAgingSummary,
refreshARAgingSummary,
// #ownProps
numberFormat,
onNumberFormatSubmit,
}) {
const { isARAgingFetching, refetch } = useARAgingSummaryContext();
const handleFilterToggleClick = () => {
toggleFilterARAgingSummary();
};
// Handles re-calculate report button.
const handleRecalcReport = () => {
refreshARAgingSummary(true);
refetch();
};
// Handle number format submit.
const handleNumberFormatSubmit = (numberFormat) => {
@@ -80,7 +80,7 @@ function ARAgingSummaryActionsBar({
<NumberFormatDropdown
numberFormat={numberFormat}
onSubmit={handleNumberFormatSubmit}
submitDisabled={ARAgingSummaryLoading}
submitDisabled={isARAgingFetching}
/>
}
minimal={true}
@@ -118,7 +118,4 @@ function ARAgingSummaryActionsBar({
export default compose(
withARAgingSummaryActions,
withARAgingSummary(({ receivableAgingSummaryLoading }) => ({
ARAgingSummaryLoading: receivableAgingSummaryLoading,
})),
)(ARAgingSummaryActionsBar);

View File

@@ -17,24 +17,21 @@ import { compose } from 'utils';
* AR Aging Summary Report - Drawer Header.
*/
function ARAgingSummaryHeader({
// #ownProps
pageFilter,
onSubmitFilter,
receivableAgingFilter,
// #withReceivableAgingSummary
receivableAgingRefresh,
// #withReceivableAgingSummaryActions
refreshReceivableAgingSummary,
toggleFilterARAgingSummary,
}) {
const validationSchema = Yup.object().shape({
asDate: Yup.date().required().label('asDate'),
agingBeforeDays: Yup.number()
agingDaysBefore: Yup.number()
.required()
.integer()
.positive()
.label('agingBeforeDays'),
.label('agingDaysBefore'),
agingPeriods: Yup.number()
.required()
.integer()
@@ -44,12 +41,13 @@ function ARAgingSummaryHeader({
// Initial values.
const initialValues = {
asDate: moment(pageFilter.asDate).toDate(),
agingBeforeDays: 30,
agingDaysBefore: 30,
agingPeriods: 3,
};
// Handle form submit.
const handleSubmit = (values, { setSubmitting }) => {
onSubmitFilter(values);
toggleFilterARAgingSummary();
setSubmitting(false);
};
// Handle cancel button click.
@@ -89,10 +87,7 @@ function ARAgingSummaryHeader({
export default compose(
withARAgingSummaryActions,
withARAgingSummary(
({ receivableAgingSummaryFilter, receivableAgingSummaryRefresh }) => ({
receivableAgingFilter: receivableAgingSummaryFilter,
receivableAgingRefresh: receivableAgingSummaryRefresh,
}),
),
withARAgingSummary(({ receivableAgingSummaryFilter }) => ({
receivableAgingFilter: receivableAgingSummaryFilter,
})),
)(ARAgingSummaryHeader);

View File

@@ -12,17 +12,16 @@ import { FormattedMessage as T } from 'react-intl';
import classNames from 'classnames';
import { CustomersMultiSelect, Row, Col, FieldHint } from 'components';
import { momentFormatter } from 'utils';
// import withCustomers from 'containers/Customers/withCustomers';
import { compose } from 'redux';
import { useARAgingSummaryContext } from './ARAgingSummaryProvider';
/**
* AR Aging Summary - Drawer Header - General Fields.
*/
function ARAgingSummaryHeaderGeneral({
// #withCustomers
customers,
}) {
export default function ARAgingSummaryHeaderGeneral() {
// AR Aging summary context.
const { customers } = useARAgingSummaryContext();
return (
<div>
<Row>
@@ -53,7 +52,7 @@ function ARAgingSummaryHeaderGeneral({
<Row>
<Col xs={5}>
<FastField name={'agingBeforeDays'}>
<FastField name={'agingDaysBefore'}>
{({ field, meta: { error, touched } }) => (
<FormGroup
label={<T id={'aging_before_days'} />}
@@ -104,9 +103,4 @@ function ARAgingSummaryHeaderGeneral({
</Row>
</div>
);
}
export default compose(
// withCustomers(({ customers }) => ({
// customers,
// })),
)(ARAgingSummaryHeaderGeneral);
}

View File

@@ -0,0 +1,47 @@
import React, { useMemo, createContext, useContext } from 'react';
import DashboardInsider from 'components/Dashboard/DashboardInsider';
import { useARAgingSummaryReport, useCustomers } from 'hooks/query';
import { transformFilterFormToQuery } from '../common';
const ARAgingSummaryContext = createContext();
/**
* A/R aging summary provider.
*/
function ARAgingSummaryProvider({ filter, ...props }) {
// Transformes the filter from to the Url query.
const query = useMemo(() => transformFilterFormToQuery(filter), [filter]);
const {
data: ARAgingSummary,
isLoading: isARAgingLoading,
isFetching: isARAgingFetching,
refetch,
} = useARAgingSummaryReport(query);
// Retrieve the customers list.
const {
data: { customers },
isFetching: isCustomersFetching,
} = useCustomers();
const provider = {
ARAgingSummary,
customers,
isARAgingLoading,
isARAgingFetching,
isCustomersFetching,
refetch,
};
return (
<DashboardInsider name={'AR-Aging-Summary'}>
<ARAgingSummaryContext.Provider value={provider} {...props} />
</DashboardInsider>
);
}
const useARAgingSummaryContext = () => useContext(ARAgingSummaryContext);
export { ARAgingSummaryProvider, useARAgingSummaryContext };

View File

@@ -1,72 +1,25 @@
import React, { useMemo, useCallback } from 'react';
import { FormattedMessage as T, useIntl } from 'react-intl';
import React, { useCallback } from 'react';
import { useIntl } from 'react-intl';
import DataTable from 'components/DataTable';
import FinancialSheet from 'components/FinancialSheet';
import withARAgingSummary from './withARAgingSummary';
import { compose, getColumnWidth } from 'utils';
import { useARAgingSummaryContext } from './ARAgingSummaryProvider';
import { useARAgingSummaryColumns } from './components';
/**
* AR aging summary table sheet.
*/
function ReceivableAgingSummaryTable({
// #withReceivableAgingSummary
receivableAgingRows,
receivableAgingLoading,
receivableAgingColumns,
export default function ReceivableAgingSummaryTable({
// #ownProps
onFetchData,
organizationName,
}) {
const { formatMessage } = useIntl();
const agingColumns = useMemo(() => {
return receivableAgingColumns.map((agingColumn) => {
return `${agingColumn.before_days} - ${
agingColumn.to_days || 'And Over'
}`;
});
}, [receivableAgingColumns]);
// AR aging summary report context.
const { ARAgingSummary, isARAgingFetching } = useARAgingSummaryContext();
const columns = useMemo(
() => [
{
Header: <T id={'customer_name'} />,
accessor: 'name',
className: 'customer_name',
sticky: 'left',
width: 240,
textOverview: true,
},
{
Header: <T id={'current'} />,
accessor: 'current',
className: 'current',
width: getColumnWidth(receivableAgingRows, `current`, {
minWidth: 120,
}),
},
...agingColumns.map((agingColumn, index) => ({
Header: agingColumn,
accessor: `aging-${index }`,
width: getColumnWidth(receivableAgingRows, `aging-${index }`, {
minWidth: 120,
}),
})),
{
Header: (<T id={'total'} />),
id: 'total',
accessor: 'total',
className: 'total',
width: getColumnWidth(receivableAgingRows, 'total', {
minWidth: 120,
}),
},
],
[receivableAgingRows, agingColumns],
);
// AR aging summary columns.
const columns = useARAgingSummaryColumns();
const rowClassNames = (row) => [`row-type--${row.original.rowType}`];
@@ -80,12 +33,12 @@ function ReceivableAgingSummaryTable({
name={'receivable-aging-summary'}
sheetType={formatMessage({ id: 'receivable_aging_summary' })}
asDate={new Date()}
loading={receivableAgingLoading}
loading={isARAgingFetching}
>
<DataTable
className="bigcapital-datatable--financial-report"
columns={columns}
data={receivableAgingRows}
data={ARAgingSummary.tableRows}
rowClassNames={rowClassNames}
onFetchData={handleFetchData}
noInitialFetch={true}
@@ -94,17 +47,3 @@ function ReceivableAgingSummaryTable({
</FinancialSheet>
);
}
export default compose(
withARAgingSummary(
({
receivableAgingSummaryLoading,
receivableAgingSummaryColumns,
receivableAgingSummaryRows,
}) => ({
receivableAgingLoading: receivableAgingSummaryLoading,
receivableAgingColumns: receivableAgingSummaryColumns,
receivableAgingRows: receivableAgingSummaryRows,
}),
),
)(ReceivableAgingSummaryTable);

View File

@@ -0,0 +1,58 @@
import React from 'react';
import { useARAgingSummaryContext } from './ARAgingSummaryProvider';
import { getColumnWidth } from 'utils';
import { FormattedMessage as T } from 'react-intl';
/**
* Retrieve AR aging summary columns.
*/
export const useARAgingSummaryColumns = () => {
const {
ARAgingSummary: { tableRows, columns },
} = useARAgingSummaryContext();
const agingColumns = React.useMemo(() => {
return columns.map(
(agingColumn) =>
`${agingColumn.before_days} - ${agingColumn.to_days || 'And Over'}`,
);
}, [columns]);
return React.useMemo(
() => [
{
Header: <T id={'customer_name'} />,
accessor: 'name',
className: 'customer_name',
sticky: 'left',
width: 240,
textOverview: true,
},
{
Header: <T id={'current'} />,
accessor: 'current',
className: 'current',
width: getColumnWidth(tableRows, `current`, {
minWidth: 120,
}),
},
...agingColumns.map((agingColumn, index) => ({
Header: agingColumn,
accessor: `aging-${index}`,
width: getColumnWidth(tableRows, `aging-${index}`, {
minWidth: 120,
}),
})),
{
Header: <T id={'total'} />,
id: 'total',
accessor: 'total',
className: 'total',
width: getColumnWidth(tableRows, 'total', {
minWidth: 120,
}),
},
],
[tableRows, agingColumns],
);
};