diff --git a/client/src/config/financialReportsMenu.js b/client/src/config/financialReportsMenu.js
index f32beaf2f..fc82eef1b 100644
--- a/client/src/config/financialReportsMenu.js
+++ b/client/src/config/financialReportsMenu.js
@@ -10,7 +10,8 @@ export const financialReportMenus = [
},
{
title: 'Trial Balance Sheet',
- desc: 'Summarizes the credit and debit balance of each account in your chart of accounts at a specific point in time.',
+ desc:
+ 'Summarizes the credit and debit balance of each account in your chart of accounts at a specific point in time.',
link: '/financial-reports/trial-balance-sheet',
},
{
@@ -21,22 +22,26 @@ export const financialReportMenus = [
},
{
title: 'Profit/Loss Report',
- desc: "Reports the revenues, costs and expenses incurred during a specific point in time with comparison period(s).",
+ desc:
+ 'Reports the revenues, costs and expenses incurred during a specific point in time with comparison period(s).',
link: '/financial-reports/profit-loss-sheet',
},
{
title: 'General Ledger Report',
- desc: "Reports every transaction going in and out of your accounts and organized by accounts and date to monitoring activity of accounts.",
+ desc:
+ 'Reports every transaction going in and out of your accounts and organized by accounts and date to monitoring activity of accounts.',
link: '/financial-reports/general-ledger',
},
{
title: 'Receivable Aging Summary',
- desc: "Summarize total unpaid balances of customers invoices with number of days the unpaid invoice is overdue.",
+ desc:
+ 'Summarize total unpaid balances of customers invoices with number of days the unpaid invoice is overdue.',
link: '/financial-reports/receivable-aging-summary',
},
{
title: 'Payable Aging Summary',
- desc: "Summarize total unpaid balances of vendors purchase invoices with the number of days the unpaid invoice is overdue.",
+ desc:
+ 'Summarize total unpaid balances of vendors purchase invoices with the number of days the unpaid invoice is overdue.',
link: '/financial-reports/payable-aging-summary',
},
],
@@ -54,16 +59,37 @@ export const SalesAndPurchasesReportMenus = [
link: '/financial-reports/purchases-by-items',
},
{
- title: 'Sales by Items',
+ title: 'Sales By Items',
desc:
- "Summarize the business’s sold items quantity, income and average income rate of each item during a specific point in time.",
+ 'Summarize the business’s sold items quantity, income and average income rate of each item during a specific point in time.',
link: '/financial-reports/sales-by-items',
},
{
title: 'Inventory valuation',
- desc: 'Summarize the business’s purchase items quantity, cost and average cost rate of each item during a specific point in time.',
+ desc:
+ 'Summarize the business’s purchase items quantity, cost and average cost rate of each item during a specific point in time.',
link: '/financial-reports/inventory-valuation',
},
+ {
+ title: 'Customer Balance summary',
+ desc: '',
+ link: '/financial-reports/customers-balance-summary',
+ },
+ {
+ title: 'Vendors Balance summary',
+ desc: '',
+ link: '/financial-reports/vendors-balance-summary',
+ },
+ {
+ title: 'Customers Transactions',
+ desc: '',
+ link: '/financial-reports/transactions-by-customers',
+ },
+ {
+ title: 'Vendors Transactions',
+ desc: '',
+ link: '/financial-reports/transactions-by-vendors',
+ },
],
},
];
diff --git a/client/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummary.js b/client/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummary.js
new file mode 100644
index 000000000..f45480599
--- /dev/null
+++ b/client/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummary.js
@@ -0,0 +1,87 @@
+import React, { useEffect, useState } from 'react';
+import moment from 'moment';
+
+import 'style/pages/FinancialStatements/ContactsBalanceSummary.scss';
+
+import { FinancialStatement } from 'components';
+import DashboardPageContent from 'components/Dashboard/DashboardPageContent';
+
+import CustomersBalanceSummaryActionsBar from './CustomersBalanceSummaryActionsBar';
+import CustomersBalanceSummaryHeader from './CustomersBalanceSummaryHeader';
+import CustomersBalanceSummaryTable from './CustomersBalanceSummaryTable';
+
+import { CustomersBalanceLoadingBar } from './components';
+import { CustomersBalanceSummaryProvider } from './CustomersBalanceSummaryProvider';
+import withCustomersBalanceSummaryActions from './withCustomersBalanceSummaryActions';
+
+import withSettings from 'containers/Settings/withSettings';
+
+import { compose } from 'redux';
+
+/**
+ * Customers Balance summary.
+ */
+function CustomersBalanceSummary({
+ // #withPreferences
+ organizationName,
+
+ // #withCustomersBalanceSummaryActions
+ toggleCustomerBalanceFilterDrawer,
+}) {
+
+ const [filter, setFilter] = useState({
+ asDate: moment().endOf('day').format('YYYY-MM-DD'),
+ });
+
+ // Handle re-fetch customers balance summary after filter change.
+ const handleFilterSubmit = (filter) => {
+ const _filter = {
+ ...filter,
+ asDate: moment(filter.asDate).format('YYYY-MM-DD'),
+ };
+ setFilter({ ..._filter });
+ };
+
+ // Handle number format.
+ const handleNumberFormat = (values) => {
+ setFilter({
+ ...filter,
+ numberFormat: values,
+ });
+ };
+
+ useEffect(
+ () => () => {
+ toggleCustomerBalanceFilterDrawer(false);
+ },
+ [toggleCustomerBalanceFilterDrawer],
+ );
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+export default compose(
+ withSettings(({ organizationSettings }) => ({
+ organizationName: organizationSettings.name,
+ })),
+ withCustomersBalanceSummaryActions,
+)(CustomersBalanceSummary);
diff --git a/client/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryActionsBar.js b/client/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryActionsBar.js
new file mode 100644
index 000000000..d70519dd5
--- /dev/null
+++ b/client/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryActionsBar.js
@@ -0,0 +1,133 @@
+import React from 'react';
+import {
+ NavbarGroup,
+ Button,
+ Classes,
+ NavbarDivider,
+ Popover,
+ PopoverInteractionKind,
+ Position,
+} from '@blueprintjs/core';
+import { FormattedMessage as T } from 'react-intl';
+import classNames from 'classnames';
+
+import Icon from 'components/Icon';
+import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
+import NumberFormatDropdown from 'components/NumberFormatDropdown';
+
+import withCustomersBalanceSummary from './withCustomersBalanceSummary';
+import withCustomersBalanceSummaryActions from './withCustomersBalanceSummaryActions';
+import { useCustomersBalanceSummaryContext } from './CustomersBalanceSummaryProvider';
+import { compose, saveInvoke } from 'utils';
+
+/**
+ * customer balance summary action bar.
+ */
+function CustomersBalanceSummaryActionsBar({
+ // #ownProps
+ numberFormat,
+ onNumberFormatSubmit,
+
+ //#withCustomersBalanceSummary
+ isFilterDrawerOpen,
+
+ //#withCustomersBalanceSummaryActions
+ toggleCustomerBalanceFilterDrawer,
+}) {
+ const {
+ refetch,
+ isCustomersBalanceLoading,
+ } = useCustomersBalanceSummaryContext();
+
+ // handle filter toggle click.
+ const handleFilterToggleClick = () => {
+ toggleCustomerBalanceFilterDrawer();
+ };
+
+ // Handle recalculate the report button.
+ const handleRecalcReport = () => {
+ refetch();
+ };
+
+ // Handle number format form submit.
+ const handleNumberFormatSubmit = (values) => {
+ saveInvoke(onNumberFormatSubmit, values);
+ };
+
+ return (
+
+
+ }
+ onClick={handleRecalcReport}
+ icon={ }
+ />
+
+ }
+ text={
+ isFilterDrawerOpen ? (
+
+ ) : (
+
+ )
+ }
+ onClick={handleFilterToggleClick}
+ active={isFilterDrawerOpen}
+ />
+
+
+ }
+ minimal={true}
+ interactionKind={PopoverInteractionKind.CLICK}
+ position={Position.BOTTOM_LEFT}
+ >
+ }
+ icon={ }
+ />
+
+
+
+ }
+ icon={ }
+ />
+
+
+
+
+ }
+ text={ }
+ />
+ }
+ text={ }
+ />
+
+
+ );
+}
+export default compose(
+ withCustomersBalanceSummary(({ customersBalanceDrawerFilter }) => ({
+ isFilterDrawerOpen: customersBalanceDrawerFilter,
+ })),
+ withCustomersBalanceSummaryActions,
+)(CustomersBalanceSummaryActionsBar);
diff --git a/client/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryGeneralPanel.js b/client/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryGeneralPanel.js
new file mode 100644
index 000000000..9ecdd7aa5
--- /dev/null
+++ b/client/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryGeneralPanel.js
@@ -0,0 +1,70 @@
+import React from 'react';
+import { FastField } from 'formik';
+import { DateInput } from '@blueprintjs/datetime';
+import {
+ FormGroup,
+ Position,
+ Classes,
+ Checkbox,
+} from '@blueprintjs/core';
+import { FormattedMessage as T } from 'react-intl';
+
+import { Row, Col, FieldHint } from 'components';
+import {
+ momentFormatter,
+ tansformDateValue,
+ inputIntent,
+ handleDateChange,
+} from 'utils';
+
+/**
+ * Customers balance header - general panel.
+ */
+export default function CustomersBalanceSummaryGeneralPanel() {
+ return (
+
+
+
+
+ {({ form, field: { value }, meta: { error } }) => (
+ }
+ labelInfo={ }
+ fill={true}
+ intent={inputIntent({ error })}
+ >
+ {
+ form.setFieldValue('asDate', selectedDate);
+ })}
+ popoverProps={{ position: Position.BOTTOM, minimal: true }}
+ minimal={true}
+ fill={true}
+ />
+
+ )}
+
+
+
+
+
+
+ {({ field }) => (
+ }>
+
+
+ )}
+
+
+
+
+ );
+}
diff --git a/client/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryHeader.js b/client/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryHeader.js
new file mode 100644
index 000000000..6e1b3ec58
--- /dev/null
+++ b/client/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryHeader.js
@@ -0,0 +1,91 @@
+import React from 'react';
+import * as Yup from 'yup';
+import { Formik, Form } from 'formik';
+import moment from 'moment';
+import { Tabs, Tab, Button, Intent } from '@blueprintjs/core';
+import { FormattedMessage as T, useIntl } from 'react-intl';
+
+import FinancialStatementHeader from 'containers/FinancialStatements/FinancialStatementHeader';
+import withCustomersBalanceSummary from './withCustomersBalanceSummary';
+import withCustomersBalanceSummaryActions from './withCustomersBalanceSummaryActions';
+import CustomersBalanceSummaryGeneralPanel from './CustomersBalanceSummaryGeneralPanel';
+
+import { compose } from 'utils';
+
+/**
+ * Customers balance summary.
+ */
+function CustomersBalanceSummaryHeader({
+ // #ownProps
+ onSubmitFilter,
+ pageFilter,
+
+ //#withCustomersBalanceSummary
+ customersBalanceDrawerFilter,
+
+ //#withCustomersBalanceSummaryActions
+ toggleCustomerBalanceFilterDrawer,
+}) {
+
+ // validation schema.
+ const validationSchema = Yup.object().shape({
+ asDate: Yup.date().required().label('asDate'),
+ });
+
+ // filter form initial values.
+ const initialValues = {
+ ...pageFilter,
+ asDate: moment(pageFilter.asDate).toDate(),
+ };
+
+ // handle form submit.
+ const handleSubmit = (values, { setSubmitting }) => {
+ onSubmitFilter(values);
+ toggleCustomerBalanceFilterDrawer(false);
+ setSubmitting(false);
+ };
+
+ // handle close drawer.
+ const handleDrawerClose = () => {
+ toggleCustomerBalanceFilterDrawer(false);
+ };
+
+ return (
+
+
+
+
+
+ );
+}
+
+export default compose(
+ withCustomersBalanceSummary(({ customersBalanceDrawerFilter }) => ({
+ customersBalanceDrawerFilter,
+ })),
+ withCustomersBalanceSummaryActions,
+)(CustomersBalanceSummaryHeader);
diff --git a/client/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryProvider.js b/client/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryProvider.js
new file mode 100644
index 000000000..8ab7f48ab
--- /dev/null
+++ b/client/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryProvider.js
@@ -0,0 +1,42 @@
+import React, { createContext, useContext } from 'react';
+import FinancialReportPage from '../FinancialReportPage';
+import { useCustomerBalanceSummaryReport } from 'hooks/query';
+import { transformFilterFormToQuery } from '../common';
+
+const CustomersBalanceSummaryContext = createContext();
+
+/**
+ * Customers balance summary provider.
+ */
+function CustomersBalanceSummaryProvider({ filter, ...props }) {
+
+ // const query = React.useMemo(() => transformFilterFormToQuery(filter), [
+ // filter,
+ // ]);
+
+ const {
+ data: CustomerBalanceSummary,
+ isLoading: isCustomersBalanceLoading,
+ isFetching: isCustomersBalanceFetching,
+ refetch
+ } = useCustomerBalanceSummaryReport(filter, {
+ keepPreviousData: true,
+ });
+
+ const provider = {
+ CustomerBalanceSummary,
+ isCustomersBalanceFetching,
+ isCustomersBalanceLoading,
+ refetch,
+ };
+ return (
+
+
+
+ );
+}
+
+const useCustomersBalanceSummaryContext = () =>
+ useContext(CustomersBalanceSummaryContext);
+
+export { CustomersBalanceSummaryProvider, useCustomersBalanceSummaryContext };
diff --git a/client/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryTable.js b/client/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryTable.js
new file mode 100644
index 000000000..57ee2655f
--- /dev/null
+++ b/client/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryTable.js
@@ -0,0 +1,48 @@
+import React, { useMemo, useCallback } from 'react';
+import { useIntl } from 'react-intl';
+import classNames from 'classnames';
+
+import FinancialSheet from 'components/FinancialSheet';
+import DataTable from 'components/DataTable';
+
+import { useCustomersBalanceSummaryContext } from './CustomersBalanceSummaryProvider';
+import { useCustomersSummaryColumns } from './components';
+
+/**
+ * customers balance summary table.
+ */
+export default function CustomersBalanceSummaryTable({
+ // #ownProps
+ companyName,
+}) {
+ const { formatMessage } = useIntl();
+
+ const {
+ isCustomersBalanceLoading,
+ CustomerBalanceSummary: { tableRows },
+ } = useCustomersBalanceSummaryContext();
+
+ const columns = useCustomersSummaryColumns();
+
+ const rowClassNames = (row) => {
+ return [`row-type--${row.original.rowTypes}`];
+ };
+
+ return (
+
+
+
+ );
+}
diff --git a/client/src/containers/FinancialStatements/CustomersBalanceSummary/components.js b/client/src/containers/FinancialStatements/CustomersBalanceSummary/components.js
new file mode 100644
index 000000000..0ac61d5c9
--- /dev/null
+++ b/client/src/containers/FinancialStatements/CustomersBalanceSummary/components.js
@@ -0,0 +1,48 @@
+import React from 'react';
+import { formatMessage } from 'services/intl';
+
+import { If } from 'components';
+import FinancialLoadingBar from '../FinancialLoadingBar';
+import { useCustomersBalanceSummaryContext } from './CustomersBalanceSummaryProvider';
+
+/**
+ * Retrieve customers balance summary columns.
+ */
+export const useCustomersSummaryColumns = () => {
+ return React.useMemo(
+ () => [
+ {
+ Header: formatMessage({ id: 'customer_name' }),
+ accessor: 'cells[0].value',
+ className: 'customer_name',
+ width: 240,
+ },
+ {
+ Header: formatMessage({ id: 'total' }),
+ accessor: 'cells[1].value',
+ className: 'total',
+ width: 140,
+ },
+ {
+ Header: formatMessage({ id: 'percentage_of_column' }),
+ accessor: 'cells[2].value',
+ className: 'total',
+ width: 140,
+ },
+ ],
+ [formatMessage],
+ );
+};
+
+/**
+ * customers balance summary loading bar.
+ */
+export function CustomersBalanceLoadingBar() {
+ const { isCustomersBalanceFetching } = useCustomersBalanceSummaryContext();
+
+ return (
+
+
+
+ );
+}
diff --git a/client/src/containers/FinancialStatements/CustomersBalanceSummary/withCustomersBalanceSummary.js b/client/src/containers/FinancialStatements/CustomersBalanceSummary/withCustomersBalanceSummary.js
new file mode 100644
index 000000000..80cf7382a
--- /dev/null
+++ b/client/src/containers/FinancialStatements/CustomersBalanceSummary/withCustomersBalanceSummary.js
@@ -0,0 +1,15 @@
+import { connect } from 'react-redux';
+import { getCustomersBalanceSummaryFilterDrawer } from 'store/financialStatement/financialStatements.selectors';
+
+export default (mapState) => {
+ const mapStateToProps = (state, props) => {
+ const mapped = {
+ customersBalanceDrawerFilter: getCustomersBalanceSummaryFilterDrawer(
+ state,
+ props,
+ ),
+ };
+ return mapState ? mapState(mapped, state, props) : mapped;
+ };
+ return connect(mapStateToProps);
+};
diff --git a/client/src/containers/FinancialStatements/CustomersBalanceSummary/withCustomersBalanceSummaryActions.js b/client/src/containers/FinancialStatements/CustomersBalanceSummary/withCustomersBalanceSummaryActions.js
new file mode 100644
index 000000000..b7679f2b1
--- /dev/null
+++ b/client/src/containers/FinancialStatements/CustomersBalanceSummary/withCustomersBalanceSummaryActions.js
@@ -0,0 +1,9 @@
+import { connect } from 'react-redux';
+import { toggleCustomersBalanceSummaryFilterDrawer } from 'store/financialStatement/financialStatements.actions';
+
+const mapActionsToProps = (dispatch) => ({
+ toggleCustomerBalanceFilterDrawer: (toggle) =>
+ dispatch(toggleCustomersBalanceSummaryFilterDrawer(toggle)),
+});
+
+export default connect(null, mapActionsToProps);
diff --git a/client/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummary.js b/client/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummary.js
new file mode 100644
index 000000000..05b35d20e
--- /dev/null
+++ b/client/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummary.js
@@ -0,0 +1,87 @@
+import React, { useEffect, useState } from 'react';
+import moment from 'moment';
+
+import 'style/pages/FinancialStatements/ContactsBalanceSummary.scss';
+
+import { FinancialStatement } from 'components';
+import DashboardPageContent from 'components/Dashboard/DashboardPageContent';
+
+import VendorsBalanceSummaryActionsBar from './VendorsBalanceSummaryActionsBar';
+import VendorsBalanceSummaryHeader from './VendorsBalanceSummaryHeader';
+import VendorsBalanceSummaryTable from './VendorsBalanceSummaryTable';
+
+import { VendorsBalanceSummaryProvider } from './VendorsBalanceSummaryProvider';
+import { VendorsSummarySheetLoadingBar } from './components';
+import withVendorsBalanceSummaryActions from './withVendorsBalanceSummaryActions';
+
+import withSettings from 'containers/Settings/withSettings';
+
+import { compose } from 'utils';
+
+/**
+ * Vendors Balance summary.
+ */
+function VendorsBalanceSummary({
+ // #withPreferences
+ organizationName,
+
+ // #withVendorsBalanceSummaryActions
+ toggleVendorSummaryFilterDrawer,
+}) {
+ const [filter, setFilter] = useState({
+ asDate: moment().endOf('day').format('YYYY-MM-DD'),
+ });
+
+ // Handle refetch vendors balance summary.
+ const handleFilterSubmit = (filter) => {
+ const _filter = {
+ ...filter,
+ asDate: moment(filter.asDate).format('YYYY-MM-DD'),
+ };
+ setFilter(_filter);
+ };
+
+ // Handle number format submit.
+ const handleNumberFormatSubmit = (format) => {
+ setFilter({
+ ...filter,
+ numberFormat: format,
+ });
+ };
+
+ useEffect(
+ () => () => {
+ toggleVendorSummaryFilterDrawer(false);
+ },
+ [toggleVendorSummaryFilterDrawer],
+ );
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default compose(
+ withSettings(({ organizationSettings }) => ({
+ organizationName: organizationSettings?.name,
+ })),
+ withVendorsBalanceSummaryActions,
+)(VendorsBalanceSummary);
diff --git a/client/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryActionsBar.js b/client/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryActionsBar.js
new file mode 100644
index 000000000..f7f01655c
--- /dev/null
+++ b/client/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryActionsBar.js
@@ -0,0 +1,126 @@
+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 { Icon } from 'components';
+import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
+import NumberFormatDropdown from 'components/NumberFormatDropdown';
+
+import withVendorsBalanceSummary from './withVendorsBalanceSummary';
+import withVendorsBalanceSummaryActions from './withVendorsBalanceSummaryActions';
+import { useVendorsBalanceSummaryContext } from './VendorsBalanceSummaryProvider';
+
+import { saveInvoke, compose } from 'utils';
+
+/**
+ * Vendors balance summary action bar.
+ */
+function VendorsBalanceSummaryActionsBar({
+ //#ownProps
+ numberFormat,
+ onNumberFormatSubmit,
+
+ // #withVendorsBalanceSummary
+ isFilterDrawerOpen,
+
+ // #withVendorsBalanceSummaryActions
+ toggleVendorSummaryFilterDrawer,
+}) {
+ const {
+ isVendorsBalanceLoading,
+ refetch,
+ } = useVendorsBalanceSummaryContext();
+
+ const handleFilterToggleClick = () => {
+ toggleVendorSummaryFilterDrawer();
+ };
+
+ // handle recalculate report button.
+ const handleRecalculateReport = () => {
+ refetch();
+ };
+
+ // handle number format submit.
+ const handleNumberFormatSubmit = (numberFormat) => {
+ saveInvoke(onNumberFormatSubmit, numberFormat);
+ };
+
+ return (
+
+
+ }
+ onClick={handleRecalculateReport}
+ icon={ }
+ />
+
+ }
+ text={
+ isFilterDrawerOpen ? (
+
+ ) : (
+
+ )
+ }
+ onClick={handleFilterToggleClick}
+ active={isFilterDrawerOpen}
+ />
+
+
+ }
+ minimal={true}
+ interactionKind={PopoverInteractionKind.CLICK}
+ position={Position.BOTTOM_LEFT}
+ >
+ }
+ icon={ }
+ />
+
+
+ }
+ icon={ }
+ />
+
+
+ }
+ text={ }
+ />
+ }
+ text={ }
+ />
+
+
+ );
+}
+export default compose(
+ withVendorsBalanceSummaryActions,
+ withVendorsBalanceSummary(({ VendorsSummaryFilterDrawer }) => ({
+ isFilterDrawerOpen: VendorsSummaryFilterDrawer,
+ })),
+)(VendorsBalanceSummaryActionsBar);
diff --git a/client/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryHeader.js b/client/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryHeader.js
new file mode 100644
index 000000000..fb5be3c6f
--- /dev/null
+++ b/client/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryHeader.js
@@ -0,0 +1,89 @@
+import React from 'react';
+import * as Yup from 'yup';
+import { Formik, Form } from 'formik';
+import moment from 'moment';
+import { Tabs, Tab, Button, Intent } from '@blueprintjs/core';
+import { FormattedMessage as T } from 'react-intl';
+
+import FinancialStatementHeader from 'containers/FinancialStatements/FinancialStatementHeader';
+import withVendorsBalanceSummary from './withVendorsBalanceSummary';
+import withVendorsBalanceSummaryActions from './withVendorsBalanceSummaryActions';
+import VendorsBalanceSummaryHeaderGeneral from './VendorsBalanceSummaryHeaderGeneral';
+
+import { compose } from 'utils';
+
+/**
+ * Vendors balance summary drawer header.
+ */
+function VendorsBalanceSummaryHeader({
+ // #ownProps
+ pageFilter,
+ onSubmitFilter,
+
+ //#withVendorsBalanceSummary
+ VendorsSummaryFilterDrawer,
+
+ //#withVendorsBalanceSummaryActions
+ toggleVendorSummaryFilterDrawer,
+}) {
+ // validation schema.
+ const validationSchema = Yup.object().shape({
+ asDate: Yup.date().required().label('asDate'),
+ });
+
+ // filter form initial values.
+ const initialValues = {
+ ...pageFilter,
+ asDate: moment(pageFilter.asDate).toDate(),
+ };
+
+ // handle form submit.
+ const handleSubmit = (values, { setSubmitting }) => {
+ onSubmitFilter(values);
+ toggleVendorSummaryFilterDrawer(false);
+ setSubmitting(false);
+ };
+
+ // handle cancel button click.
+ const handleCancelClick = () => {
+ toggleVendorSummaryFilterDrawer(false);
+ };
+
+ return (
+
+
+
+
+
+ );
+}
+
+export default compose(
+ withVendorsBalanceSummary(({ VendorsSummaryFilterDrawer }) => ({
+ VendorsSummaryFilterDrawer,
+ })),
+ withVendorsBalanceSummaryActions,
+)(VendorsBalanceSummaryHeader);
diff --git a/client/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryHeaderGeneral.js b/client/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryHeaderGeneral.js
new file mode 100644
index 000000000..b7811721a
--- /dev/null
+++ b/client/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryHeaderGeneral.js
@@ -0,0 +1,64 @@
+import React from 'react';
+import { FastField } from 'formik';
+import { DateInput } from '@blueprintjs/datetime';
+import { FormGroup, Position, Classes, Checkbox } from '@blueprintjs/core';
+import { FormattedMessage as T } from 'react-intl';
+import { Row, Col, FieldHint } from 'components';
+import {
+ momentFormatter,
+ tansformDateValue,
+ inputIntent,
+ handleDateChange,
+} from 'utils';
+
+/**
+ * Vendors balance header -general panel.
+ */
+export default function VendorsBalanceSummaryHeaderGeneral() {
+ return (
+
+
+
+
+ {({ form, field: { value }, meta: { error } }) => (
+ }
+ labelInfo={ }
+ fill={true}
+ intent={inputIntent({ error })}
+ >
+ {
+ form.setFieldValue('asDate', selectedDate);
+ })}
+ popoverProps={{ position: Position.BOTTOM, minimal: true }}
+ minimal={true}
+ fill={true}
+ />
+
+ )}
+
+
+
+
+
+
+ {({ field }) => (
+ }>
+
+
+ )}
+
+
+
+
+ );
+}
diff --git a/client/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryProvider.js b/client/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryProvider.js
new file mode 100644
index 000000000..b6f5587fb
--- /dev/null
+++ b/client/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryProvider.js
@@ -0,0 +1,41 @@
+import React from 'react';
+import FinancialReportPage from '../FinancialReportPage';
+import { useVendorsBalanceSummaryReport } from 'hooks/query';
+import { transformFilterFormToQuery } from '../common';
+
+const VendorsBalanceSummaryContext = React.createContext();
+
+/**
+ * Vendors balance summary provider.
+ */
+function VendorsBalanceSummaryProvider({ filter, ...props }) {
+ // const query = React.useMemo(() => transformFilterFormToQuery(filter), [
+ // filter,
+ // ]);
+
+ const {
+ data: VendorBalanceSummary,
+ isLoading: isVendorsBalanceLoading,
+ isFetching: isVendorsBalanceFetching,
+ refetch,
+ } = useVendorsBalanceSummaryReport(filter, {
+ keepPreviousData: true,
+ });
+
+ const provider = {
+ VendorBalanceSummary,
+ isVendorsBalanceLoading,
+ isVendorsBalanceFetching,
+ refetch,
+ };
+
+ return (
+
+
+
+ );
+}
+
+const useVendorsBalanceSummaryContext = () =>
+ React.useContext(VendorsBalanceSummaryContext);
+export { VendorsBalanceSummaryProvider, useVendorsBalanceSummaryContext };
diff --git a/client/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryTable.js b/client/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryTable.js
new file mode 100644
index 000000000..043bd2c54
--- /dev/null
+++ b/client/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryTable.js
@@ -0,0 +1,47 @@
+import React from 'react';
+import { FormattedMessage as T, useIntl } from 'react-intl';
+import { DataTable } from 'components';
+import FinancialSheet from 'components/FinancialSheet';
+
+import { useVendorsBalanceColumns } from './components';
+import { useVendorsBalanceSummaryContext } from './VendorsBalanceSummaryProvider';
+
+/**
+ * Vendors balance summary table.
+ */
+export default function VendorsBalanceSummaryTable({
+ //#ownProps
+ organizationName,
+}) {
+ const { formatMessage } = useIntl();
+
+ const {
+ VendorBalanceSummary,
+ isVendorsBalanceLoading,
+ } = useVendorsBalanceSummaryContext();
+
+ // vendors balance summary columns.
+ const columns = useVendorsBalanceColumns();
+
+ const rowClassNames = (row) => {
+ return [`row-type--${row.original.rowTypes}`];
+ };
+
+ return (
+
+
+
+ );
+}
diff --git a/client/src/containers/FinancialStatements/VendorsBalanceSummary/components.js b/client/src/containers/FinancialStatements/VendorsBalanceSummary/components.js
new file mode 100644
index 000000000..f6d9f5315
--- /dev/null
+++ b/client/src/containers/FinancialStatements/VendorsBalanceSummary/components.js
@@ -0,0 +1,47 @@
+import React, { useMemo } from 'react';
+import { formatMessage } from 'services/intl';
+
+import { If } from 'components';
+import { getColumnWidth } from 'utils';
+import FinancialLoadingBar from '../FinancialLoadingBar';
+import { useVendorsBalanceSummaryContext } from './VendorsBalanceSummaryProvider';
+
+/**
+ * Retrieve vendors balance summary columns.
+ */
+export const useVendorsBalanceColumns = () => {
+ return useMemo(() => [
+ {
+ Header: formatMessage({ id: 'vendor_name' }),
+ accessor: 'cells[0].value',
+ className: 'customer_name',
+ width: 240,
+ sticky: 'left',
+ textOverview: true,
+ },
+ {
+ Header: formatMessage({ id: 'total' }),
+ accessor: 'cells[1].value',
+ className: 'total',
+ width: 140,
+ },
+ {
+ Header: formatMessage({ id: 'percentage_of_column' }),
+ accessor: 'cells[2].value',
+ // className: 'total',
+ width: 140,
+ },
+ ]);
+};
+
+/**
+ * vendors balance summary loading bar.
+ */
+export function VendorsSummarySheetLoadingBar() {
+ const { isVendorsBalanceFetching } = useVendorsBalanceSummaryContext();
+ return (
+
+
+
+ );
+}
diff --git a/client/src/containers/FinancialStatements/VendorsBalanceSummary/withVendorsBalanceSummary.js b/client/src/containers/FinancialStatements/VendorsBalanceSummary/withVendorsBalanceSummary.js
new file mode 100644
index 000000000..674e01716
--- /dev/null
+++ b/client/src/containers/FinancialStatements/VendorsBalanceSummary/withVendorsBalanceSummary.js
@@ -0,0 +1,15 @@
+import { connect } from 'react-redux';
+import { getVendorsBalanceSummaryFilterDrawer } from 'store/financialStatement/financialStatements.selectors';
+
+export default (mapState) => {
+ const mapStateToProps = (state, props) => {
+ const mapped = {
+ VendorsSummaryFilterDrawer: getVendorsBalanceSummaryFilterDrawer(
+ state,
+ props,
+ ),
+ };
+ return mapState ? mapState(mapped, state, props) : mapped;
+ };
+ return connect(mapStateToProps);
+};
diff --git a/client/src/containers/FinancialStatements/VendorsBalanceSummary/withVendorsBalanceSummaryActions.js b/client/src/containers/FinancialStatements/VendorsBalanceSummary/withVendorsBalanceSummaryActions.js
new file mode 100644
index 000000000..a2881f338
--- /dev/null
+++ b/client/src/containers/FinancialStatements/VendorsBalanceSummary/withVendorsBalanceSummaryActions.js
@@ -0,0 +1,9 @@
+import { connect } from 'react-redux';
+import { toggleVendorsBalanceSummaryFilterDrawer } from 'store/financialStatement/financialStatements.actions';
+
+const mapActionsToProps = (dispatch) => ({
+ toggleVendorSummaryFilterDrawer: (toggle) =>
+ dispatch(toggleVendorsBalanceSummaryFilterDrawer(toggle)),
+});
+
+export default connect(null, mapActionsToProps);
diff --git a/client/src/hooks/query/financialReports.js b/client/src/hooks/query/financialReports.js
index 1ec454c3b..3096bfc7a 100644
--- a/client/src/hooks/query/financialReports.js
+++ b/client/src/hooks/query/financialReports.js
@@ -287,3 +287,80 @@ export function useSalesByItems(query, props) {
},
);
}
+
+/**
+ * Retrieve customers balance summary report.
+ */
+export function useCustomerBalanceSummaryReport(query, props) {
+ return useRequestQuery(
+ [t.FINANCIAL_REPORT, t.CUSTOMERS_BALANCE_SUMMARY, query],
+ {
+ method: 'get',
+ url: '/financial_statements/customer-balance-summary',
+ params: query,
+ },
+ {
+ select: (res) => ({
+ columns: res.data.columns,
+ query: res.data.query,
+ tableRows: res.data.table.rows,
+ }),
+ defaultData: {
+ tableRows: [],
+ query: {},
+ },
+ ...props,
+ },
+ );
+}
+
+/**
+ * Retrieve vendors balance summary report.
+ */
+export function useVendorsBalanceSummaryReport(query, props) {
+ return useRequestQuery(
+ [t.FINANCIAL_REPORT, t.VENDORS_BALANCE_SUMMARY, query],
+ {
+ method: 'get',
+ url: '/financial_statements/vendor-balance-summary',
+ params: query,
+ },
+ {
+ select: (res) => ({
+ columns: res.data.columns,
+ query: res.data.query,
+ tableRows: res.data.table.rows,
+ }),
+ defaultData: {
+ tableRows: [],
+ query: {},
+ },
+ ...props,
+ },
+ );
+}
+
+/**
+ * Retrieve customers transcations report.
+ */
+export function useCustomersTranscationsReport(query, props) {
+ return useRequestQuery(
+ [t.FINANCIAL_REPORT, t.CUSTOMERS_TRANSACTIONS, query],
+ {
+ method: 'get',
+ url: '/financial_statements/transactions-by-customers',
+ params: query,
+ },
+ {
+ select: (res) => ({
+ data: res.data.table,
+ tableRows: res.data.table.rows,
+ }),
+ defaultData: {
+ tableRows: [],
+ data: [],
+ },
+ ...props,
+ },
+ );
+}
diff --git a/client/src/routes/dashboard.js b/client/src/routes/dashboard.js
index 52a816b2e..1c9fa0e68 100644
--- a/client/src/routes/dashboard.js
+++ b/client/src/routes/dashboard.js
@@ -112,7 +112,8 @@ export default [
import('containers/FinancialStatements/GeneralLedger/GeneralLedger'),
),
breadcrumb: 'General Ledger',
- hint: "Reports every transaction going in and out of your accounts and organized by accounts and date to monitoring activity of accounts.",
+ hint:
+ 'Reports every transaction going in and out of your accounts and organized by accounts and date to monitoring activity of accounts.',
hotkey: 'shift+4',
pageTitle: formatMessage({ id: 'general_ledger' }),
backLink: true,
@@ -124,7 +125,8 @@ export default [
import('containers/FinancialStatements/BalanceSheet/BalanceSheet'),
),
breadcrumb: 'Balance Sheet',
- hint: "Reports a company's assets, liabilities and shareholders' equity at a specific point in time with comparison period(s).",
+ hint:
+ "Reports a company's assets, liabilities and shareholders' equity at a specific point in time with comparison period(s).",
hotkey: 'shift+1',
pageTitle: formatMessage({ id: 'balance_sheet' }),
backLink: true,
@@ -138,7 +140,8 @@ export default [
),
),
breadcrumb: 'Trial Balance Sheet',
- hint: "Summarizes the credit and debit balance of each account in your chart of accounts at a specific point in time. ",
+ hint:
+ 'Summarizes the credit and debit balance of each account in your chart of accounts at a specific point in time. ',
hotkey: 'shift+5',
pageTitle: formatMessage({ id: 'trial_balance_sheet' }),
backLink: true,
@@ -150,7 +153,8 @@ export default [
import('containers/FinancialStatements/ProfitLossSheet/ProfitLossSheet'),
),
breadcrumb: 'Profit Loss Sheet',
- hint: "Reports the revenues, costs and expenses incurred during a specific point in time with comparison period(s).",
+ hint:
+ 'Reports the revenues, costs and expenses incurred during a specific point in time with comparison period(s).',
hotkey: 'shift+2',
pageTitle: formatMessage({ id: 'profit_loss_sheet' }),
backLink: true,
@@ -162,7 +166,8 @@ export default [
import('containers/FinancialStatements/ARAgingSummary/ARAgingSummary'),
),
breadcrumb: 'Receivable Aging Summary',
- hint: "Summarize total unpaid balances of customers invoices with number of days the unpaid invoice is overdue.",
+ hint:
+ 'Summarize total unpaid balances of customers invoices with number of days the unpaid invoice is overdue.',
pageTitle: formatMessage({ id: 'receivable_aging_summary' }),
backLink: true,
sidebarExpand: false,
@@ -173,7 +178,8 @@ export default [
import('containers/FinancialStatements/APAgingSummary/APAgingSummary'),
),
breadcrumb: 'Payable Aging Summary',
- hint: "Summarize total unpaid balances of vendors purchase invoices with the number of days the unpaid invoice is overdue.",
+ hint:
+ 'Summarize total unpaid balances of vendors purchase invoices with the number of days the unpaid invoice is overdue.',
pageTitle: formatMessage({ id: 'payable_aging_summary' }),
backLink: true,
sidebarExpand: false,
@@ -184,7 +190,8 @@ export default [
import('containers/FinancialStatements/Journal/Journal'),
),
breadcrumb: 'Journal Sheet',
- hint: "The debit and credit entries of system transactions, sorted by date.",
+ hint:
+ 'The debit and credit entries of system transactions, sorted by date.',
hotkey: 'shift+3',
pageTitle: formatMessage({ id: 'journal_sheet' }),
sidebarExpand: false,
@@ -210,7 +217,8 @@ export default [
),
breadcrumb: 'Sales by Items',
pageTitle: formatMessage({ id: 'sales_by_items' }),
- hint: 'Summarize the business’s sold items quantity, income and average income rate of each item during a specific point in time.',
+ hint:
+ 'Summarize the business’s sold items quantity, income and average income rate of each item during a specific point in time.',
backLink: true,
sidebarExpand: false,
},
@@ -222,11 +230,64 @@ export default [
),
),
breadcrumb: 'Inventory Valuation ',
- hint: 'Summerize your transactions for each inventory item and how they affect quantity, valuation and weighted average.',
+ hint:
+ 'Summerize your transactions for each inventory item and how they affect quantity, valuation and weighted average.',
pageTitle: formatMessage({ id: 'inventory_valuation' }),
backLink: true,
sidebarExpand: false,
},
+ {
+ path: `/financial-reports/customers-balance-summary`,
+ component: lazy(() =>
+ import(
+ 'containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummary'
+ ),
+ ),
+ breadcrumb: 'Customers Balance Summary ',
+ hint: '..',
+ pageTitle: formatMessage({ id: 'customers_balance_summary' }),
+ backLink: true,
+ sidebarExpand: false,
+ },
+ {
+ path: `/financial-reports/vendors-balance-summary`,
+ component: lazy(() =>
+ import(
+ 'containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummary'
+ ),
+ ),
+ breadcrumb: 'Vendors Balance Summary ',
+ hint: '..',
+ pageTitle: formatMessage({ id: 'vendors_balance_summary' }),
+ backLink: true,
+ sidebarExpand: false,
+ },
+ {
+ path: `/financial-reports/transactions-by-customers`,
+ // component: lazy(() =>
+ // import(
+ // 'containers/FinancialStatements/CustomersTransactions/CustomersTransactions'
+ // ),
+ // ),
+ breadcrumb: 'Customers Transactions ',
+ hint: '..',
+ pageTitle: formatMessage({ id: 'customers_transactions' }),
+ backLink: true,
+ sidebarExpand: false,
+ },
+ {
+ path: `/financial-reports/vendors-transactions`,
+ // component: lazy(() =>
+ // import(
+ // 'containers/FinancialStatements/'
+ // ),
+ // ),
+ breadcrumb: 'Vendors Transactions ',
+ hint: '..',
+ pageTitle: formatMessage({ id: 'vendors_transactions' }),
+ backLink: true,
+ sidebarExpand: false,
+ },
{
path: '/financial-reports',
component: lazy(() =>
diff --git a/client/src/store/financialStatement/financialStatements.actions.js b/client/src/store/financialStatement/financialStatements.actions.js
index eaca5f0f4..86f2e9506 100644
--- a/client/src/store/financialStatement/financialStatements.actions.js
+++ b/client/src/store/financialStatement/financialStatements.actions.js
@@ -128,3 +128,54 @@ export function toggleInventoryValuationFilterDrawer(toggle) {
},
};
}
+
+
+/**
+ * Toggles display of the customers balance summary filter drawer.
+ * @param {boolean} toggle
+ */
+ export function toggleCustomersBalanceSummaryFilterDrawer(toggle) {
+ return {
+ type: `${t.CUSTOMERS_BALANCE_SUMMARY}/${t.DISPLAY_FILTER_DRAWER_TOGGLE}`,
+ payload: {
+ toggle,
+ },
+ };
+}
+/**
+ * Toggles display of the vendors balance summary filter drawer.
+ * @param {boolean} toggle
+ */
+ export function toggleVendorsBalanceSummaryFilterDrawer(toggle) {
+ return {
+ type: `${t.VENDORS_BALANCE_SUMMARY}/${t.DISPLAY_FILTER_DRAWER_TOGGLE}`,
+ payload: {
+ toggle,
+ },
+ };
+}
+/**
+ * Toggles display of the customers transactions filter drawer.
+ * @param {boolean} toggle
+ */
+ export function toggleCustomersTransactionsFilterDrawer(toggle) {
+ return {
+ type: `${t.CUSTOMERS_TRANSACTIONS}/${t.DISPLAY_FILTER_DRAWER_TOGGLE}`,
+ payload: {
+ toggle,
+ },
+ };
+}
+
+// /**
+// * Toggles display of the vendors transactions filter drawer.
+// * @param {boolean} toggle
+// */
+// export function toggleVendorsTransactionsFilterDrawer(toggle) {
+// return {
+// type: `${t.VENDORS_TRANSACTIONS}/${t.DISPLAY_FILTER_DRAWER_TOGGLE}`,
+// payload: {
+// toggle,
+// },
+// };
+// }
\ No newline at end of file
diff --git a/client/src/store/financialStatement/financialStatements.reducer.js b/client/src/store/financialStatement/financialStatements.reducer.js
index d21666577..e0b725b33 100644
--- a/client/src/store/financialStatement/financialStatements.reducer.js
+++ b/client/src/store/financialStatement/financialStatements.reducer.js
@@ -33,6 +33,18 @@ const initialState = {
inventoryValuation: {
displayFilterDrawer: false,
},
+ customersBalanceSummary: {
+ displayFilterDrawer: false,
+ },
+ vendorsBalanceSummary: {
+ displayFilterDrawer: false,
+ },
+ customersTransactions: {
+ displayFilterDrawer: false,
+ },
+ vendorsTransactions: {
+ displayFilterDrawer: false,
+ },
};
/**
@@ -63,4 +75,20 @@ export default createReducer(initialState, {
t.INVENTORY_VALUATION,
'inventoryValuation',
),
+ ...financialStatementFilterToggle(
+ t.CUSTOMERS_BALANCE_SUMMARY,
+ 'customersBalanceSummary',
+ ),
+ ...financialStatementFilterToggle(
+ t.VENDORS_BALANCE_SUMMARY,
+ 'vendorsBalanceSummary',
+ ),
+ ...financialStatementFilterToggle(
+ t.CUSTOMERS_TRANSACTIONS,
+ 'customersTransactions',
+ ),
+ ...financialStatementFilterToggle(
+ t.VENDORS_TRANSACTIONS,
+ 'vendorsTransactions',
+ ),
});
diff --git a/client/src/store/financialStatement/financialStatements.selectors.js b/client/src/store/financialStatement/financialStatements.selectors.js
index 92a9f7410..c87c10cc9 100644
--- a/client/src/store/financialStatement/financialStatements.selectors.js
+++ b/client/src/store/financialStatement/financialStatements.selectors.js
@@ -49,6 +49,22 @@ export const inventoryValuationFilterDrawerSelector = (state) => {
return filterDrawerByTypeSelector('inventoryValuation')(state);
};
+export const customerBalanceSummaryFilterDrawerSelector = (state) => {
+ return filterDrawerByTypeSelector('customersBalanceSummary')(state);
+};
+
+export const vendorsBalanceSummaryFilterDrawerSelector = (state) => {
+ return filterDrawerByTypeSelector('vendorsBalanceSummary')(state);
+};
+
+export const customersTransactionsFilterDrawerSelector = (state) => {
+ return filterDrawerByTypeSelector('customersTransactions')(state);
+};
+
+export const vendorsTransactionsFilterDrawerSelector = (state) => {
+ return filterDrawerByTypeSelector('vendorsTransactions')(state);
+};
+
/**
* Retrieve balance sheet filter drawer.
*/
@@ -156,3 +172,42 @@ export const getInventoryValuationFilterDrawer = createSelector(
return isOpen;
},
);
+
+/**
+ * Retrieve customers balance summary filter drawer.
+ */
+export const getCustomersBalanceSummaryFilterDrawer = createSelector(
+ customerBalanceSummaryFilterDrawerSelector,
+ (isOpen) => {
+ return isOpen;
+ },
+);
+/**
+ * Retrieve vendors balance summary filter drawer.
+ */
+export const getVendorsBalanceSummaryFilterDrawer = createSelector(
+ vendorsBalanceSummaryFilterDrawerSelector,
+ (isOpen) => {
+ return isOpen;
+ },
+);
+
+/**
+ * Retrieve customers transactions filter drawer.
+ */
+export const getCustomersTransactionsFilterDrawer = createSelector(
+ customersTransactionsFilterDrawerSelector,
+ (isOpen) => {
+ return isOpen;
+ },
+);
+
+/**
+ * Retrieve vendors transactions filter drawer.
+ */
+export const getVendorsTransactionsFilterDrawer = createSelector(
+ vendorsTransactionsFilterDrawerSelector,
+ (isOpen) => {
+ return isOpen;
+ },
+);
diff --git a/client/src/store/financialStatement/financialStatements.types.js b/client/src/store/financialStatement/financialStatements.types.js
index f5fabee35..f80a94ada 100644
--- a/client/src/store/financialStatement/financialStatements.types.js
+++ b/client/src/store/financialStatement/financialStatements.types.js
@@ -10,4 +10,8 @@ export default {
PURCHASES_BY_ITEMS: 'PURCHASES_BY_ITEMS',
SALES_BY_ITEMS: 'SALES_BY_ITEMS',
INVENTORY_VALUATION: 'INVENTORY_VALUATION',
+ CUSTOMERS_BALANCE_SUMMARY: 'CUSTOMERS BALANCE SUMMARY',
+ VENDORS_BALANCE_SUMMARY: 'VENDORS BALANCE SUMMARY',
+ CUSTOMERS_TRANSACTIONS: 'CUSTOMERS TRANSACTIONS',
+ // VENDORS_TRANSACTIONS: 'CUSTOMERS TRANSACTIONS',
};
diff --git a/client/src/style/pages/FinancialStatements/ContactsBalanceSummary.scss b/client/src/style/pages/FinancialStatements/ContactsBalanceSummary.scss
new file mode 100644
index 000000000..107c2b340
--- /dev/null
+++ b/client/src/style/pages/FinancialStatements/ContactsBalanceSummary.scss
@@ -0,0 +1,31 @@
+.financial-sheet {
+ &--customers-balance-summary,
+ &--vendors-balance-summary {
+ .financial-sheet__table {
+ .thead,
+ .tbody {
+ .tr .td.customer_name ~ .td,
+ .tr .th.customer_name ~ .th {
+ text-align: right;
+ }
+ }
+ .tbody {
+ .tr:not(.no-results) {
+ .td {
+ border-bottom: 0;
+ padding-top: 0.4rem;
+ padding-bottom: 0.4rem;
+ }
+ &.row-type--TOTAL {
+ font-weight: 500;
+
+ .td {
+ border-top: 1px solid #bbb;
+ border-bottom: 3px double #333;
+ }
+ }
+ }
+ }
+ }
+ }
+}