diff --git a/client/src/components/DialogsContainer.js b/client/src/components/DialogsContainer.js
index 6277ace96..61f694480 100644
--- a/client/src/components/DialogsContainer.js
+++ b/client/src/components/DialogsContainer.js
@@ -1,7 +1,6 @@
import React, { lazy } from 'react';
import AccountFormDialog from 'containers/Dialogs/AccountFormDialog';
-
import InviteUserDialog from 'containers/Dialogs/InviteUserDialog';
import ItemCategoryDialog from 'containers/Dialogs/ItemCategoryDialog';
import CurrencyFormDialog from 'containers/Dialogs/CurrencyFormDialog';
diff --git a/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummary.js b/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummary.js
new file mode 100644
index 000000000..3e1090854
--- /dev/null
+++ b/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummary.js
@@ -0,0 +1,127 @@
+import React, { useEffect, useState, useCallback } from 'react';
+import { useIntl } from 'react-intl';
+import { queryCache, useQuery } from 'react-query';
+import moment from 'moment';
+
+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 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';
+
+/**
+ * AR aging summary report.
+ */
+function ReceivableAgingSummarySheet({
+ // #withSettings
+ organizationName,
+
+ // #withDashboardActions
+ changePageTitle,
+ setDashboardBackLink,
+
+ // #withARAgingSummaryActions
+ requestReceivableAgingSummary,
+ refreshARAgingSummary,
+ toggleFilterARAgingSummary,
+
+ // #withARAgingSummary
+ ARAgingSummaryRefresh,
+}) {
+ const { formatMessage } = useIntl();
+ const [query, setQuery] = useState({
+ asDate: moment().endOf('day').format('YYYY-MM-DD'),
+ agingBeforeDays: 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(() => {
+ // Show the back link on dashboard topbar.
+ setDashboardBackLink(true);
+
+ return () => {
+ // Hide the back link on dashboard topbar.
+ setDashboardBackLink(false);
+ };
+ }, [setDashboardBackLink]);
+
+ // 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) => {}, []);
+
+ const handleFilterSubmit = useCallback(
+ (filter) => {
+ const _filter = {
+ ...filter,
+ asDate: moment(filter.asDate).format('YYYY-MM-DD'),
+ };
+ setQuery(_filter);
+ refreshARAgingSummary(true);
+ toggleFilterARAgingSummary(false);
+ },
+ [refreshARAgingSummary, toggleFilterARAgingSummary],
+ );
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default compose(
+ withDashboardActions,
+ withARAgingSummaryActions,
+ withSettings(({ organizationSettings }) => ({
+ organizationName: organizationSettings.name,
+ })),
+ withARAgingSummary(({ ARAgingSummaryRefresh }) => ({
+ ARAgingSummaryRefresh: ARAgingSummaryRefresh,
+ })),
+)(ReceivableAgingSummarySheet);
diff --git a/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryActionsBar.js b/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryActionsBar.js
new file mode 100644
index 000000000..cd826052c
--- /dev/null
+++ b/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryActionsBar.js
@@ -0,0 +1,94 @@
+import React from 'react';
+import {
+ NavbarDivider,
+ NavbarGroup,
+ Classes,
+ Button,
+ Popover,
+ PopoverInteractionKind,
+ Position,
+} from '@blueprintjs/core';
+import { FormattedMessage as T } from 'react-intl';
+import classNames from 'classnames';
+
+import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
+import Icon from 'components/Icon';
+
+import withARAgingSummary from './withARAgingSummary';
+import withARAgingSummaryActions from './withARAgingSummaryActions';
+
+import { compose } from 'utils';
+
+/**
+ * AR Aging summary sheet - Actions bar.
+ */
+function ARAgingSummaryActionsBar({
+ // #withReceivableAging
+ receivableAgingFilter,
+
+ // #withReceivableAgingActions
+ toggleFilterARAgingSummary,
+ refreshARAgingSummary,
+}) {
+ const handleFilterToggleClick = () => {
+ toggleFilterARAgingSummary();
+ };
+ // Handles re-calculate report button.
+ const handleRecalcReport = () => {
+ refreshARAgingSummary(true);
+ };
+
+ return (
+
+
+ }
+ onClick={handleRecalcReport}
+ icon={}
+ />
+
+
+ }
+ text={
+ receivableAgingFilter ? (
+
+ ) : (
+
+ )
+ }
+ onClick={handleFilterToggleClick}
+ active={receivableAgingFilter}
+ />
+
+
+ }
+ icon={}
+ />
+
+
+ }
+ text={}
+ />
+ }
+ text={}
+ />
+
+
+ );
+}
+
+export default compose(
+ withARAgingSummaryActions,
+ withARAgingSummary(({ receivableAgingSummaryFilter }) => ({
+ receivableAgingFilter: receivableAgingSummaryFilter,
+ })),
+)(ARAgingSummaryActionsBar);
diff --git a/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryHeader.js b/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryHeader.js
new file mode 100644
index 000000000..ad7649bad
--- /dev/null
+++ b/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryHeader.js
@@ -0,0 +1,98 @@
+import React from 'react';
+import { FormattedMessage as T } from 'react-intl';
+import { Formik, Form } from 'formik';
+import * as Yup from 'yup';
+import moment from 'moment';
+import { Tabs, Tab, Button, Intent } from '@blueprintjs/core';
+
+import FinancialStatementHeader from 'containers/FinancialStatements/FinancialStatementHeader';
+import ARAgingSummaryHeaderGeneral from './ARAgingSummaryHeaderGeneral';
+
+import withARAgingSummary from './withARAgingSummary';
+import withARAgingSummaryActions from './withARAgingSummaryActions';
+
+import { compose } from 'utils';
+
+/**
+ * AR Aging Summary Report - Drawer Header.
+ */
+function ARAgingSummaryHeader({
+ pageFilter,
+ onSubmitFilter,
+ receivableAgingFilter,
+
+ // #withReceivableAgingSummary
+ receivableAgingRefresh,
+
+ // #withReceivableAgingSummaryActions
+ refreshReceivableAgingSummary,
+ toggleFilterARAgingSummary,
+}) {
+ const validationSchema = Yup.object().shape({
+ asDate: Yup.date().required().label('asDate'),
+ agingBeforeDays: Yup.number()
+ .required()
+ .integer()
+ .positive()
+ .label('agingBeforeDays'),
+ agingPeriods: Yup.number()
+ .required()
+ .integer()
+ .positive()
+ .label('agingPeriods'),
+ });
+ // Initial values.
+ const initialValues = {
+ asDate: moment(pageFilter.asDate).toDate(),
+ agingBeforeDays: 30,
+ agingPeriods: 3,
+ };
+ // Handle form submit.
+ const handleSubmit = (values, { setSubmitting }) => {
+ onSubmitFilter(values);
+ setSubmitting(false);
+ };
+ // Handle cancel button click.
+ const handleCancelClick = () => {
+ toggleFilterARAgingSummary();
+ };
+
+ return (
+
+
+
+
+
+ );
+}
+
+export default compose(
+ withARAgingSummaryActions,
+ withARAgingSummary(
+ ({ receivableAgingSummaryFilter, receivableAgingSummaryRefresh }) => ({
+ receivableAgingFilter: receivableAgingSummaryFilter,
+ receivableAgingRefresh: receivableAgingSummaryRefresh,
+ }),
+ ),
+)(ARAgingSummaryHeader);
diff --git a/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryHeaderGeneral.js b/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryHeaderGeneral.js
new file mode 100644
index 000000000..c90dd9554
--- /dev/null
+++ b/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryHeaderGeneral.js
@@ -0,0 +1,76 @@
+import React from 'react';
+import { FastField } from 'formik';
+import { DateInput } from '@blueprintjs/datetime';
+import { Intent, FormGroup, InputGroup, Position } from '@blueprintjs/core';
+import { FormattedMessage as T } from 'react-intl';
+import { Row, Col, FieldHint } from 'components';
+import { momentFormatter } from 'utils';
+
+/**
+ * AR Aging Summary - Drawer Header - General Fields.
+ */
+export default function ARAgingSummaryHeaderGeneral({}) {
+ return (
+
+
+
+
+ {({ form, field: { value }, meta: { error, touched } }) => (
+ }
+ labelInfo={}
+ fill={true}
+ intent={error && Intent.DANGER}
+ >
+ {
+ form.setFieldValue('asDate', selectedDate);
+ }}
+ popoverProps={{ position: Position.BOTTOM, minimal: true }}
+ minimal={true}
+ fill={true}
+ />
+
+ )}
+
+
+
+
+
+
+
+ {({ field, meta: { error, touched } }) => (
+ }
+ labelInfo={}
+ className={'form-group--aging-before-days'}
+ intent={error && Intent.DANGER}
+ >
+
+
+ )}
+
+
+
+
+
+
+
+ {({ field, meta: { error, touched } }) => (
+ }
+ labelInfo={}
+ className={'form-group--aging-periods'}
+ intent={error && Intent.DANGER}
+ >
+
+
+ )}
+
+
+
+
+ );
+}
diff --git a/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryTable.js b/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryTable.js
new file mode 100644
index 000000000..9e2db87b7
--- /dev/null
+++ b/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryTable.js
@@ -0,0 +1,103 @@
+import React, { useMemo, useCallback } from 'react';
+import { FormattedMessage as T, useIntl } from 'react-intl';
+import DataTable from 'components/DataTable';
+import FinancialSheet from 'components/FinancialSheet';
+
+import withARAgingSummary from './withARAgingSummary';
+
+import { compose } from 'utils';
+
+/**
+ * AR aging summary table sheet.
+ */
+function ReceivableAgingSummaryTable({
+ // #withReceivableAgingSummary
+ receivableAgingRows,
+ receivableAgingLoading,
+ receivableAgingColumns,
+
+ // #ownProps
+ onFetchData,
+ organizationName,
+}) {
+ const { formatMessage } = useIntl();
+
+ const agingColumns = useMemo(() => {
+ return receivableAgingColumns.map((agingColumn) => {
+ return `${agingColumn.before_days} - ${
+ agingColumn.to_days || 'And Over'
+ }`;
+ });
+ }, [receivableAgingColumns]);
+
+ const columns = useMemo(
+ () => [
+ {
+ Header: ,
+ accessor: 'name',
+ className: 'customer_name',
+ sticky: 'left',
+ width: 200,
+ },
+ {
+ Header: ,
+ accessor: 'current',
+ className: 'current',
+ width: 120,
+ },
+ ...agingColumns.map((agingColumn, index) => ({
+ Header: agingColumn,
+ accessor: `aging-${index }`,
+ width: 120,
+ })),
+ {
+ Header: (),
+ id: 'total',
+ accessor: 'total',
+ className: 'total',
+ width: 140,
+ },
+ ],
+ [agingColumns],
+ );
+
+ const rowClassNames = (row) => [`row-type--${row.original.rowType}`];
+
+ const handleFetchData = useCallback((...args) => {
+ // onFetchData && onFetchData(...args);
+ }, []);
+
+ return (
+
+
+
+ );
+}
+
+export default compose(
+ withARAgingSummary(
+ ({
+ receivableAgingSummaryLoading,
+ receivableAgingSummaryColumns,
+ receivableAgingSummaryRows,
+ }) => ({
+ receivableAgingLoading: receivableAgingSummaryLoading,
+ receivableAgingColumns: receivableAgingSummaryColumns,
+ receivableAgingRows: receivableAgingSummaryRows,
+ }),
+ ),
+)(ReceivableAgingSummaryTable);
diff --git a/client/src/containers/FinancialStatements/ARAgingSummary/common.js b/client/src/containers/FinancialStatements/ARAgingSummary/common.js
new file mode 100644
index 000000000..96bd39a7e
--- /dev/null
+++ b/client/src/containers/FinancialStatements/ARAgingSummary/common.js
@@ -0,0 +1,5 @@
+import { mapKeys, snakeCase } from 'lodash';
+
+export const transfromFilterFormToQuery = (form) => {
+ return mapKeys(form, (v, k) => snakeCase(k));
+};
\ No newline at end of file
diff --git a/client/src/containers/FinancialStatements/ARAgingSummary/withARAgingSummary.js b/client/src/containers/FinancialStatements/ARAgingSummary/withARAgingSummary.js
new file mode 100644
index 000000000..c2a93c923
--- /dev/null
+++ b/client/src/containers/FinancialStatements/ARAgingSummary/withARAgingSummary.js
@@ -0,0 +1,36 @@
+import { connect } from 'react-redux';
+import {
+ getFinancialSheetFactory,
+ getFinancialSheetAccountsFactory,
+ getFinancialSheetColumnsFactory,
+ getFinancialSheetQueryFactory,
+ getFinancialSheetTableRowsFactory,
+} from 'store/financialStatement/financialStatements.selectors';
+
+export default (mapState) => {
+ const mapStateToProps = (state, props) => {
+ const getARAgingSheet = getFinancialSheetFactory('receivableAgingSummary');
+ const getARAgingSheetColumns = getFinancialSheetColumnsFactory(
+ 'receivableAgingSummary',
+ );
+ const getARAgingSheetRows = getFinancialSheetTableRowsFactory(
+ 'receivableAgingSummary',
+ );
+ const {
+ loading,
+ filter,
+ refresh,
+ } = state.financialStatements.receivableAgingSummary;
+
+ const mapped = {
+ receivableAgingSummarySheet: getARAgingSheet(state, props),
+ receivableAgingSummaryColumns: getARAgingSheetColumns(state, props),
+ receivableAgingSummaryRows: getARAgingSheetRows(state, props),
+ receivableAgingSummaryLoading: loading,
+ receivableAgingSummaryFilter: filter,
+ ARAgingSummaryRefresh: refresh,
+ };
+ return mapState ? mapState(mapped, state, props) : mapped;
+ };
+ return connect(mapStateToProps);
+};
diff --git a/client/src/containers/FinancialStatements/ReceivableAgingSummary/withReceivableAgingSummaryActions.js b/client/src/containers/FinancialStatements/ARAgingSummary/withARAgingSummaryActions.js
similarity index 84%
rename from client/src/containers/FinancialStatements/ReceivableAgingSummary/withReceivableAgingSummaryActions.js
rename to client/src/containers/FinancialStatements/ARAgingSummary/withARAgingSummaryActions.js
index 2e0923a12..228e233d6 100644
--- a/client/src/containers/FinancialStatements/ReceivableAgingSummary/withReceivableAgingSummaryActions.js
+++ b/client/src/containers/FinancialStatements/ARAgingSummary/withARAgingSummaryActions.js
@@ -7,11 +7,11 @@ import {
const mapActionsToProps = (dispatch) => ({
requestReceivableAgingSummary: (query) =>
dispatch(fetchReceivableAgingSummary({ query })),
- toggleFilterReceivableAgingSummary: () =>
+ toggleFilterARAgingSummary: () =>
dispatch({
type: 'RECEIVABLE_AGING_SUMMARY_FILTER_TOGGLE',
}),
- refreshReceivableAgingSummary: (refresh) =>
+ refreshARAgingSummary: (refresh) =>
dispatch(receivableAgingSummaryRefresh(refresh)),
});
diff --git a/client/src/containers/FinancialStatements/BalanceSheet/BalanceSheet.js b/client/src/containers/FinancialStatements/BalanceSheet/BalanceSheet.js
index 5446c9d54..0e8eeffa3 100644
--- a/client/src/containers/FinancialStatements/BalanceSheet/BalanceSheet.js
+++ b/client/src/containers/FinancialStatements/BalanceSheet/BalanceSheet.js
@@ -71,7 +71,7 @@ function BalanceSheet({
// Hide the back link on dashboard topbar.
setDashboardBackLink(false);
};
- });
+ }, [setDashboardBackLink]);
// Handle re-fetch balance sheet after filter change.
const handleFilterSubmit = useCallback(
diff --git a/client/src/containers/FinancialStatements/BalanceSheet/BalanceSheetActionsBar.js b/client/src/containers/FinancialStatements/BalanceSheet/BalanceSheetActionsBar.js
index ad79d6d36..c03943d8d 100644
--- a/client/src/containers/FinancialStatements/BalanceSheet/BalanceSheetActionsBar.js
+++ b/client/src/containers/FinancialStatements/BalanceSheet/BalanceSheetActionsBar.js
@@ -49,7 +49,13 @@ function BalanceSheetActionsBar({
}
- text={!balanceSheetFilter ? : }
+ text={
+ !balanceSheetFilter ? (
+
+ ) : (
+
+ )
+ }
onClick={handleFilterToggleClick}
active={balanceSheetFilter}
/>
diff --git a/client/src/containers/FinancialStatements/ReceivableAgingSummary/ReceivableAgingSummary.js b/client/src/containers/FinancialStatements/ReceivableAgingSummary/ReceivableAgingSummary.js
deleted file mode 100644
index 4f323a047..000000000
--- a/client/src/containers/FinancialStatements/ReceivableAgingSummary/ReceivableAgingSummary.js
+++ /dev/null
@@ -1,89 +0,0 @@
-import React, { useEffect, useState, useCallback } from 'react';
-import { useIntl } from 'react-intl';
-import { useQuery } from 'react-query';
-
-import moment from 'moment';
-import { FinancialStatement } from 'components';
-
-import DashboardInsider from 'components/Dashboard/DashboardInsider';
-import ReceivableAgingSummaryActionsBar from './ReceivableAgingSummaryActionsBar';
-import DashboardPageContent from 'components/Dashboard/DashboardPageContent';
-import ReceivableAgingSummaryHeader from './ReceivableAgingSummaryHeader'
-import ReceivableAgingSummaryTable from './ReceivableAgingSummaryTable';
-
-import withDashboardActions from 'containers/Dashboard/withDashboardActions';
-import withReceivableAgingSummaryActions from './withReceivableAgingSummaryActions';
-import { compose } from 'utils';
-
-
-function ReceivableAgingSummarySheet({
- // #withDashboardActions
- changePageTitle,
-
- // #withReceivableAgingSummaryActions
- requestReceivableAgingSummary,
-}) {
- const { formatMessage } = useIntl();
- const [query, setQuery] = useState({
- as_date: moment().endOf('day').format('YYYY-MM-DD'),
- aging_before_days: 30,
- aging_periods: 3,
- });
- const [refresh, setRefresh] = useState(true);
-
- useEffect(() => {
- changePageTitle(formatMessage({ id: 'receivable_aging_summary' }));
- }, []);
-
- const fetchSheet = useQuery(
- ['receivable-aging-summary', query],
- (key, q) => requestReceivableAgingSummary(q),
- { manual: true });
-
- // Handle fetch the data of receivable aging summary sheet.
- const handleFetchData = useCallback((...args) => {
- setRefresh(true);
- }, []);
-
- const handleFilterSubmit = useCallback((filter) => {
- const _filter = {
- ...filter,
- as_date: moment(filter.as_date).format('YYYY-MM-DD'),
- };
- setQuery(_filter);
- setRefresh(true);
- }, []);
-
- useEffect(() => {
- if (refresh) {
- fetchSheet.refetch({ force: true });
- setRefresh(false);
- }
- }, [fetchSheet, refresh]);
-
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-}
-
-export default compose(
- withDashboardActions,
- withReceivableAgingSummaryActions
-)(ReceivableAgingSummarySheet);
\ No newline at end of file
diff --git a/client/src/containers/FinancialStatements/ReceivableAgingSummary/ReceivableAgingSummaryActionsBar.js b/client/src/containers/FinancialStatements/ReceivableAgingSummary/ReceivableAgingSummaryActionsBar.js
deleted file mode 100644
index ae7a0b4cc..000000000
--- a/client/src/containers/FinancialStatements/ReceivableAgingSummary/ReceivableAgingSummaryActionsBar.js
+++ /dev/null
@@ -1,110 +0,0 @@
-import React from 'react';
-import {
- NavbarDivider,
- NavbarGroup,
- Classes,
- Button,
- Popover,
- PopoverInteractionKind,
- Position,
-} from "@blueprintjs/core";
-import { FormattedMessage as T } from 'react-intl';
-import classNames from 'classnames';
-
-import DashboardActionsBar from "components/Dashboard/DashboardActionsBar";
-import Icon from 'components/Icon';
-import { If } from 'components';
-
-import withReceivableAging from './withReceivableAgingSummary';
-import withReceivableAgingActions from './withReceivableAgingSummaryActions';
-
-import { compose } from 'utils';
-
-
-function ReceivableAgingSummaryActionsBar({
- // #withReceivableAging
- receivableAgingFilter,
-
- // #withReceivableAgingActions
- toggleFilterReceivableAgingSummary,
- refreshReceivableAgingSummary,
-}) {
- const handleFilterToggleClick = () => {
- toggleFilterReceivableAgingSummary();
- };
-
- const handleRecalcReport = () => {
- refreshReceivableAgingSummary(true);
- };
-
- return (
-
-
- }
- text={}
- />
-
-
- }
- icon={}
- onClick={handleRecalcReport}
- />
-
- }
- onClick={handleFilterToggleClick}
- icon={}
- />
-
-
-
- }
- onClick={handleFilterToggleClick}
- icon={}
- />
-
-
-
- }
- icon={}
- />
-
-
-
-
- }
- text={}
- />
- }
- text={}
- />
-
-
- )
-}
-
-export default compose(
- withReceivableAgingActions,
- withReceivableAging(({ receivableAgingSummaryFilter }) => ({
- receivableAgingFilter: receivableAgingSummaryFilter,
- })),
-)(ReceivableAgingSummaryActionsBar)
\ No newline at end of file
diff --git a/client/src/containers/FinancialStatements/ReceivableAgingSummary/ReceivableAgingSummaryHeader.js b/client/src/containers/FinancialStatements/ReceivableAgingSummary/ReceivableAgingSummaryHeader.js
deleted file mode 100644
index 59564d68f..000000000
--- a/client/src/containers/FinancialStatements/ReceivableAgingSummary/ReceivableAgingSummaryHeader.js
+++ /dev/null
@@ -1,148 +0,0 @@
-import React, { useCallback, useEffect } from 'react';
-import { useIntl, FormattedMessage as T } from 'react-intl';
-import { useFormik } from 'formik';
-import { Row, Col } from 'react-grid-system';
-import * as Yup from 'yup';
-import {
- Intent,
- FormGroup,
- InputGroup,
- Position,
- Button,
-} from '@blueprintjs/core';
-import { DateInput } from '@blueprintjs/datetime';
-import moment from 'moment';
-import FinancialStatementHeader from 'containers/FinancialStatements/FinancialStatementHeader';
-import { ErrorMessage, FieldHint, FieldRequiredHint } from 'components';
-import { momentFormatter } from 'utils';
-
-import withReceivableAging from './withReceivableAgingSummary';
-import withReceivableAgingActions from './withReceivableAgingSummaryActions';
-
-import { compose } from 'utils';
-
-
-function ReceivableAgingSummaryHeader({
- pageFilter,
- onSubmitFilter,
- receivableAgingFilter,
-
- // #withReceivableAgingSummary
- receivableAgingRefresh,
-
- // #withReceivableAgingSummaryActions
- refreshReceivableAgingSummary
-}) {
- const { formatMessage } = useIntl();
-
- const {
- values,
- errors,
- touched,
- setFieldValue,
- getFieldProps,
- submitForm,
- isSubmitting,
- } = useFormik({
- enableReinitialize: true,
- initialValues: {
- as_date: moment(pageFilter.as_date).toDate(),
- aging_before_days: 30,
- aging_periods: 3,
- },
- validationSchema: Yup.object().shape({
- as_date: Yup.date().required().label('as_date'),
- aging_before_days: Yup.number()
- .required()
- .integer()
- .positive()
- .label('aging_before_days'),
- aging_periods: Yup.number()
- .required()
- .integer()
- .positive()
- .label('aging_periods'),
- }),
- onSubmit: (values, { setSubmitting }) => {
- onSubmitFilter(values);
- setSubmitting(false);
- },
- });
-
- const handleDateChange = useCallback(
- (name) => (date) => {
- setFieldValue(name, date);
- },
- [],
- );
-
- // Handle submit filter submit button.
- useEffect(() => {
- if (receivableAgingRefresh) {
- submitForm();
- refreshReceivableAgingSummary(false);
- }
- }, [submitForm, receivableAgingRefresh]);
-
- return (
-
-
-
- }
- fill={true}
- intent={errors.as_date && Intent.DANGER}
- >
-
-
-
-
-
- }
- labelInfo={}
- className={'form-group--aging-before-days'}
- intent={errors.aging_before_days && Intent.DANGER}
- >
-
-
-
-
-
- }
- labelInfo={}
- className={'form-group--aging-periods'}
- intent={errors.aging_before_days && Intent.DANGER}
- >
-
-
-
-
-
- );
-}
-
-export default compose(
- withReceivableAgingActions,
- withReceivableAging(({ receivableAgingSummaryFilter, receivableAgingSummaryRefresh }) => ({
- receivableAgingFilter: receivableAgingSummaryFilter,
- receivableAgingRefresh: receivableAgingSummaryRefresh
- })),
-)(ReceivableAgingSummaryHeader);
diff --git a/client/src/containers/FinancialStatements/ReceivableAgingSummary/ReceivableAgingSummaryTable.js b/client/src/containers/FinancialStatements/ReceivableAgingSummary/ReceivableAgingSummaryTable.js
deleted file mode 100644
index c10bd09d2..000000000
--- a/client/src/containers/FinancialStatements/ReceivableAgingSummary/ReceivableAgingSummaryTable.js
+++ /dev/null
@@ -1,99 +0,0 @@
-import React, { useMemo, useCallback } from 'react';
-import { FormattedMessage as T, useIntl } from 'react-intl';
-import DataTable from "components/DataTable";
-import FinancialSheet from 'components/FinancialSheet';
-import Money from 'components/Money';
-
-import withSettings from 'containers/Settings/withSettings';
-
-import { compose } from 'utils';
-import withReceivableAgingSummary from './withReceivableAgingSummary';
-import withReceivableAgingSummaryTable from './withReceivableAgingSummaryTable';
-
-function ReceivableAgingSummaryTable({
- // #withPreferences
- organizationSettings,
-
- // #withReceivableAgingSummary
- receivableAgingRows,
- receivableAgingLoading,
- receivableAgingColumns,
-
- // #ownProps
- onFetchData,
-}) {
- const { formatMessage } = useIntl();
-
- const agingColumns = useMemo(() => {
- return receivableAgingColumns.map((agingColumn) => {
- return `${agingColumn.before_days} - ${agingColumn.to_days || 'And Over'}`;
- });
- }, [receivableAgingColumns]);
-
- const columns = useMemo(() => ([
- {
- Header: (),
- accessor: 'customer_name',
- className: 'customer_name',
- sticky: 'left',
- },
- ...agingColumns.map((agingColumn, index) => ({
- Header: agingColumn,
- accessor: (row) => {
- const amount = row[`aging-${index}`];
- if (row.rowType === 'total') {
- return
- }
- return amount > 0 ? amount : '';
- },
- })),
- {
- Header: (),
- id: 'total',
- accessor: (row) => {
- return ;
- },
- className: 'total',
- },
- ]), [agingColumns]);
-
- const rowClassNames = (row) => [`row-type--${row.original.rowType}`];
-
- const handleFetchData = useCallback((...args) => {
- onFetchData && onFetchData(...args);
- }, []);
-
- return (
-
-
-
-
- );
-}
-
-export default compose(
- withSettings,
- withReceivableAgingSummaryTable,
- withReceivableAgingSummary(({
- receivableAgingSummaryLoading,
- receivableAgingSummaryColumns,
- receivableAgingSummaryRows,
- }) => ({
- receivableAgingLoading: receivableAgingSummaryLoading,
- receivableAgingColumns: receivableAgingSummaryColumns,
- receivableAgingRows: receivableAgingSummaryRows,
- })),
-)(ReceivableAgingSummaryTable);
\ No newline at end of file
diff --git a/client/src/containers/FinancialStatements/ReceivableAgingSummary/withReceivableAgingSummary.js b/client/src/containers/FinancialStatements/ReceivableAgingSummary/withReceivableAgingSummary.js
deleted file mode 100644
index 95320b756..000000000
--- a/client/src/containers/FinancialStatements/ReceivableAgingSummary/withReceivableAgingSummary.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import { connect } from 'react-redux';
-import {
- getFinancialSheet,
- getFinancialSheetColumns,
- getFinancialSheetTableRows,
-} from 'store/financialStatement/financialStatements.selectors';
-
-export default (mapState) => {
- const mapStateToProps = (state, props) => {
- const { receivableAgingSummaryIndex } = props;
-
- const mapped = {
- receivableAgingSummarySheet: getFinancialSheet(
- state.financialStatements.receivableAgingSummary.sheets,
- receivableAgingSummaryIndex,
- ),
- receivableAgingSummaryColumns: getFinancialSheetColumns(
- state.financialStatements.receivableAgingSummary.sheets,
- receivableAgingSummaryIndex,
- ),
- receivableAgingSummaryRows: getFinancialSheetTableRows(
- state.financialStatements.receivableAgingSummary.sheets,
- receivableAgingSummaryIndex,
- ),
- receivableAgingSummaryLoading:
- state.financialStatements.receivableAgingSummary.loading,
- receivableAgingSummaryFilter:
- state.financialStatements.receivableAgingSummary.filter,
- receivableAgingSummaryRefresh:
- state.financialStatements.receivableAgingSummary.refresh,
- };
- return mapState ? mapState(mapped, state, props) : mapped;
- };
- return connect(mapStateToProps);
-}
\ No newline at end of file
diff --git a/client/src/containers/FinancialStatements/ReceivableAgingSummary/withReceivableAgingSummaryTable.js b/client/src/containers/FinancialStatements/ReceivableAgingSummary/withReceivableAgingSummaryTable.js
deleted file mode 100644
index 7f50ab420..000000000
--- a/client/src/containers/FinancialStatements/ReceivableAgingSummary/withReceivableAgingSummaryTable.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import { getFinancialSheetIndexByQuery } from 'store/financialStatement/financialStatements.selectors';
-import { connect } from 'react-redux';
-
-const mapStateToProps = (state, props) => {
- const { receivableAgingSummaryQuery } = props;
-
- return {
- receivableAgingSummaryIndex: getFinancialSheetIndexByQuery(
- state.financialStatements.receivableAgingSummary.sheets,
- receivableAgingSummaryQuery,
- ),
- };
-}
-export default connect(mapStateToProps);
\ No newline at end of file
diff --git a/client/src/lang/en/index.js b/client/src/lang/en/index.js
index 82c345370..b3ef465a3 100644
--- a/client/src/lang/en/index.js
+++ b/client/src/lang/en/index.js
@@ -954,4 +954,5 @@ export default {
delete_adjustment:'Delete Adjustment',
the_make_adjustment_has_been_successfully_created:
'The make adjustment has been successfully created.',
+ current: 'Current',
};
diff --git a/client/src/routes/dashboard.js b/client/src/routes/dashboard.js
index 3873e51c2..fc245fae9 100644
--- a/client/src/routes/dashboard.js
+++ b/client/src/routes/dashboard.js
@@ -135,16 +135,16 @@ export default [
}),
breadcrumb: 'Profit Loss Sheet',
},
- // {
- // path: '/financial-reports/receivable-aging-summary',
- // component: LazyLoader({
- // loader: () =>
- // import(
- // 'containers/FinancialStatements/ReceivableAgingSummary/ReceivableAgingSummary'
- // ),
- // }),
- // breadcrumb: 'Receivable Aging Summary',
- // },
+ {
+ path: '/financial-reports/receivable-aging-summary',
+ component: LazyLoader({
+ loader: () =>
+ import(
+ 'containers/FinancialStatements/ARAgingSummary/ARAgingSummary'
+ ),
+ }),
+ breadcrumb: 'Receivable Aging Summary',
+ },
{
path: `/financial-reports/journal-sheet`,
component: LazyLoader({
@@ -236,7 +236,7 @@ export default [
breadcrumb: 'Vendors',
},
- //Estimates
+ // Estimates
{
path: `/estimates/:id/edit`,
component: LazyLoader({
diff --git a/client/src/store/financialStatement/financialStatements.actions.js b/client/src/store/financialStatement/financialStatements.actions.js
index 31ef7f47d..34bd31a9f 100644
--- a/client/src/store/financialStatement/financialStatements.actions.js
+++ b/client/src/store/financialStatement/financialStatements.actions.js
@@ -157,7 +157,8 @@ export const fetchReceivableAgingSummary = ({ query }) => {
dispatch({
type: t.RECEIVABLE_AGING_SUMMARY_SET,
payload: {
- aging: response.data.aging,
+ customers: response.data.data.customers,
+ total: response.data.data.total,
columns: response.data.columns,
query,
},
@@ -172,7 +173,7 @@ export const fetchReceivableAgingSummary = ({ query }) => {
})
.catch((error) => {
reject(error);
- })
+ });
});
}
diff --git a/client/src/store/financialStatement/financialStatements.mappers.js b/client/src/store/financialStatement/financialStatements.mappers.js
index b980c5875..a73b30a21 100644
--- a/client/src/store/financialStatement/financialStatements.mappers.js
+++ b/client/src/store/financialStatement/financialStatements.mappers.js
@@ -78,6 +78,48 @@ export const generalLedgerToTableRows = (accounts) => {
}, []);
};
+export const ARAgingSummaryTableRowsMapper = (sheet, total) => {
+ const rows = [];
+
+ const mapAging = (agingPeriods) => {
+ return agingPeriods.reduce((acc, aging, index) => {
+ acc[`aging-${index}`] = aging.formatted_total;
+ return acc;
+ }, {});
+ };
+ sheet.customers.forEach((customer) => {
+ const agingRow = mapAging(customer.aging);
+
+ rows.push({
+ rowType: 'customer',
+ name: customer.customer_name,
+ ...agingRow,
+ current: customer.current.formatted_total,
+ total: customer.total.formatted_total,
+ });
+ });
+ return [
+ ...rows,
+ {
+ name: 'TOTAL',
+ rowType: 'total',
+ current: sheet.total.current.formatted_total,
+ ...mapAging(sheet.total.aging),
+ total: sheet.total.total.formatted_total,
+ }
+ ];
+};
+
+export const mapTrialBalanceSheetToRows = (sheet) => {
+ return [
+ {
+ name: 'Total',
+ ...sheet.total,
+ },
+ ...sheet.accounts,
+ ];
+};
+
export const profitLossToTableRowsMapper = (profitLoss) => {
return [
diff --git a/client/src/store/financialStatement/financialStatements.reducer.js b/client/src/store/financialStatement/financialStatements.reducer.js
index 4e1a59502..c88cff6e9 100644
--- a/client/src/store/financialStatement/financialStatements.reducer.js
+++ b/client/src/store/financialStatement/financialStatements.reducer.js
@@ -1,11 +1,12 @@
import { createReducer } from '@reduxjs/toolkit';
import t from 'store/types';
-import { omit } from 'lodash';
import {
mapBalanceSheetToTableRows,
journalToTableRowsMapper,
generalLedgerToTableRows,
- profitLossToTableRowsMapper
+ profitLossToTableRowsMapper,
+ ARAgingSummaryTableRowsMapper,
+ mapTrialBalanceSheetToRows,
} from './financialStatements.mappers';
const initialState = {
@@ -41,7 +42,7 @@ const initialState = {
filter: true,
},
receivableAgingSummary: {
- sheets: [],
+ sheet: {},
loading: false,
tableRows: [],
filter: true,
@@ -49,38 +50,6 @@ const initialState = {
},
};
-
-
-
-const mapContactAgingSummary = (sheet) => {
- const rows = [];
-
- const mapAging = (agingPeriods) => {
- return agingPeriods.reduce((acc, aging, index) => {
- acc[`aging-${index}`] = aging.formatted_total;
- return acc;
- }, {});
- };
- sheet.customers.forEach((customer) => {
- const agingRow = mapAging(customer.aging);
-
- rows.push({
- rowType: 'customer',
- customer_name: customer.customer_name,
- ...agingRow,
- total: customer.total,
- });
- });
-
- rows.push({
- rowType: 'total',
- customer_name: 'Total',
- ...mapAging(sheet.total),
- total: 0,
- });
- return rows;
-};
-
const financialStatementFilterToggle = (financialName, statePath) => {
return {
[`${financialName}_FILTER_TOGGLE`]: (state, action) => {
@@ -112,8 +81,10 @@ export default createReducer(initialState, {
...financialStatementFilterToggle('BALANCE_SHEET', 'balanceSheet'),
[t.TRAIL_BALANCE_STATEMENT_SET]: (state, action) => {
+ debugger;
const trailBalanceSheet = {
- data: action.data.data,
+ sheet: action.data.data,
+ tableRows: mapTrialBalanceSheetToRows(action.data.data),
query: action.data.query,
};
state.trialBalance.sheet = trailBalanceSheet;
@@ -154,7 +125,7 @@ export default createReducer(initialState, {
accounts: action.data.data,
tableRows: generalLedgerToTableRows(action.data.data),
};
- state.generalLedger.sheet = generalLedger;
+ state.generalLedger.sheet = generalLedger;
},
[t.GENERAL_LEDGER_SHEET_LOADING]: (state, action) => {
@@ -173,7 +144,7 @@ export default createReducer(initialState, {
columns: action.columns,
tableRows: profitLossToTableRowsMapper(action.profitLoss),
};
- state.profitLoss.sheet = profitLossSheet;
+ state.profitLoss.sheet = profitLossSheet;
},
[t.PROFIT_LOSS_SHEET_LOADING]: (state, action) => {
@@ -187,34 +158,28 @@ export default createReducer(initialState, {
...financialStatementFilterToggle('PROFIT_LOSS', 'profitLoss'),
- // [t.RECEIVABLE_AGING_SUMMARY_LOADING]: (state, action) => {
- // const { loading } = action.payload;
- // state.receivableAgingSummary.loading = loading;
- // },
+
- // [t.RECEIVABLE_AGING_SUMMARY_SET]: (state, action) => {
- // const { aging, columns, query } = action.payload;
- // const index = getFinancialSheetIndexByQuery(
- // state.receivableAgingSummary.sheets,
- // query,
- // );
+ [t.RECEIVABLE_AGING_SUMMARY_SET]: (state, action) => {
+ const { customers, total, columns, query } = action.payload;
- // const receivableSheet = {
- // query,
- // columns,
- // aging,
- // tableRows: mapContactAgingSummary(aging),
- // };
- // if (index !== -1) {
- // state.receivableAgingSummary[index] = receivableSheet;
- // } else {
- // state.receivableAgingSummary.sheets.push(receivableSheet);
- // }
- // },
- // [t.RECEIVABLE_AGING_SUMMARY_REFRESH]: (state, action) => {
- // const { refresh } = action.payload;
- // state.receivableAgingSummary.refresh = !!refresh;
- // },
+ const receivableSheet = {
+ query,
+ columns,
+ customers,
+ total,
+ tableRows: ARAgingSummaryTableRowsMapper({ customers, columns, total }),
+ };
+ state.receivableAgingSummary.sheet = receivableSheet;
+ },
+ [t.RECEIVABLE_AGING_SUMMARY_REFRESH]: (state, action) => {
+ const { refresh } = action.payload;
+ state.receivableAgingSummary.refresh = !!refresh;
+ },
+ [t.RECEIVABLE_AGING_SUMMARY_LOADING]: (state, action) => {
+ const { loading } = action.payload;
+ state.receivableAgingSummary.loading = loading;
+ },
...financialStatementFilterToggle(
'RECEIVABLE_AGING_SUMMARY',
'receivableAgingSummary',
diff --git a/client/src/style/pages/financial-statements.scss b/client/src/style/pages/financial-statements.scss
index 2c791ef75..ad8661221 100644
--- a/client/src/style/pages/financial-statements.scss
+++ b/client/src/style/pages/financial-statements.scss
@@ -145,7 +145,7 @@
}
.financial-sheet{
- border: 2px solid #EBEBEB;
+ border: 2px solid #f0f0f0;
border-radius: 10px;
min-width: 640px;
width: auto;
@@ -366,15 +366,26 @@
&--receivable-aging-summary{
.financial-sheet__table{
- .tbody{
- .row-type--total{
- font-weight: 600;
- .td{
- background-color: #fafbff;
- border-bottom-color: #666;
- border-bottom-style: dotted;
- }
+ .bigcapital-datatable{
+ .tbody,
+ .thead{
+ .tr .td.customer_name ~ .td,
+ .tr .th.customer_name ~ .th{
+ justify-content: flex-end;
+ }
+ }
+ .tbody{
+
+ .row-type--total{
+ font-weight: 600;
+
+ .td{
+ border-top-color: #BBB;
+ border-top-style: solid;
+ border-bottom: 3px double #666;
+ }
+ }
}
}
}
diff --git a/server/src/interfaces/ARAgingSummaryReport.ts b/server/src/interfaces/ARAgingSummaryReport.ts
index 9f7670ae9..581f3d5d5 100644
--- a/server/src/interfaces/ARAgingSummaryReport.ts
+++ b/server/src/interfaces/ARAgingSummaryReport.ts
@@ -25,6 +25,7 @@ export interface IARAgingSummaryCustomer {
export interface IARAgingSummaryTotal {
current: IAgingPeriodTotal,
aging: (IAgingPeriodTotal & IAgingPeriod)[],
+ total: IAgingPeriodTotal,
};
export interface IARAgingSummaryData {
diff --git a/server/src/services/FinancialStatements/AgingSummary/ARAgingSummarySheet.ts b/server/src/services/FinancialStatements/AgingSummary/ARAgingSummarySheet.ts
index d75d74245..171f529b4 100644
--- a/server/src/services/FinancialStatements/AgingSummary/ARAgingSummarySheet.ts
+++ b/server/src/services/FinancialStatements/AgingSummary/ARAgingSummarySheet.ts
@@ -96,12 +96,14 @@ export default class ARAgingSummarySheet extends AgingSummaryReport {
const customersAgingPeriods = this.customersWalker(this.contacts);
const totalAgingPeriods = this.getTotalAgingPeriods(customersAgingPeriods);
const totalCurrent = this.getTotalCurrent(customersAgingPeriods);
+ const totalCustomersTotal = this.getTotalContactsTotals(customersAgingPeriods);
return {
customers: customersAgingPeriods,
total: {
current: this.formatTotalAmount(totalCurrent),
aging: totalAgingPeriods,
+ total: this.formatTotalAmount(totalCustomersTotal),
}
};
}
diff --git a/server/src/services/FinancialStatements/AgingSummary/AgingSummary.ts b/server/src/services/FinancialStatements/AgingSummary/AgingSummary.ts
index 81fc3d393..d9e6ee048 100644
--- a/server/src/services/FinancialStatements/AgingSummary/AgingSummary.ts
+++ b/server/src/services/FinancialStatements/AgingSummary/AgingSummary.ts
@@ -79,7 +79,6 @@ export default abstract class AgingSummaryReport extends AgingReport {
return {
...agingPeriod,
total,
- formattedAmount: this.formatAmount(total),
};
});
return newAgingPeriods;
@@ -198,4 +197,11 @@ export default abstract class AgingSummaryReport extends AgingReport {
protected getAgingPeriodsTotal(agingPeriods: IAgingPeriodTotal[]): number {
return sumBy(agingPeriods, 'total');
}
+
+
+ protected getTotalContactsTotals(
+ customersSummary: IARAgingSummaryCustomer[]
+ ): number {
+ return sumBy(customersSummary, (summary) => summary.total.total);
+ }
}
diff --git a/server/src/services/Inventory/InventoryAdjustmentService.ts b/server/src/services/Inventory/InventoryAdjustmentService.ts
index 3fed1f326..a2f07e841 100644
--- a/server/src/services/Inventory/InventoryAdjustmentService.ts
+++ b/server/src/services/Inventory/InventoryAdjustmentService.ts
@@ -220,8 +220,8 @@ export default class InventoryAdjustmentService {
/**
* Publish the inventory adjustment transaction.
- * @param tenantId
- * @param inventoryAdjustmentId
+ * @param tenantId
+ * @param inventoryAdjustmentId
*/
async publishInventoryAdjustment(
tenantId: number,
@@ -239,11 +239,9 @@ export default class InventoryAdjustmentService {
inventoryAdjustmentId,
});
// Publish the inventory adjustment transaction.
- await InventoryAdjustment.query()
- .findById(inventoryAdjustmentId)
- .patch({
- publishedAt: moment().toMySqlDateTime(),
- });
+ await InventoryAdjustment.query().findById(inventoryAdjustmentId).patch({
+ publishedAt: moment().toMySqlDateTime(),
+ });
// Retrieve the inventory adjustment after the modification.
const inventoryAdjustment = await InventoryAdjustment.query()