WIP financial statements.

This commit is contained in:
Ahmed Bouhuolia
2020-03-31 16:30:38 +02:00
parent da05239e84
commit 1bf837ae17
26 changed files with 442 additions and 148 deletions

View File

@@ -1,4 +1,4 @@
import React, {useEffect, useMemo, useState} from 'react';
import React, {useEffect, useMemo, useCallback, useState} from 'react';
import DashboardConnect from 'connectors/Dashboard.connector';
import {compose} from 'utils';
import useAsync from 'hooks/async';
@@ -30,39 +30,41 @@ function BalanceSheet({
const fetchHook = useAsync(async () => {
await Promise.all([
fetchBalanceSheet(filter),
fetchBalanceSheet({
...filter,
display_columns_type: 'total',
}),
]);
setReload(false);
});
useEffect(() => {
if (!reload) { return; }
fetchHook.execute();
}, [reload]);
// Handle fetch the data of balance sheet.
const handleFetchData = useCallback(() => { fetchHook.execute(); }, [fetchHook]);
useEffect(() => {
changePageTitle('Balance Sheet');
}, []);
// Retrieve balance sheet index by the given filter query.
const balanceSheetIndex = useMemo(() => {
return getBalanceSheetIndexByQuery(filter);
}, [filter, balanceSheets]);
const balanceSheetIndex = useMemo(() =>
getBalanceSheetIndexByQuery(filter),
[filter, getBalanceSheetIndexByQuery]);
// Retreive balance sheet by the given sheet index.
const balanceSheet = useMemo(() => {
return getBalanceSheetByIndex(balanceSheetIndex);
}, [balanceSheetIndex, balanceSheets]);
const balanceSheet = useMemo(() =>
getBalanceSheetByIndex(balanceSheetIndex),
[balanceSheetIndex, getBalanceSheetByIndex]);
// Handle re-fetch balance sheet after filter change.
const handleFilterSubmit = (filter) => {
const handleFilterSubmit = useCallback((filter) => {
setFilter({
...filter,
from_date: moment(filter.from_date).format('YYYY-MM-DD'),
to_date: moment(filter.to_date).format('YYYY-MM-DD'),
});
setReload(true);
};
}, [setFilter]);
return (
<div class="financial-statement">
<BalanceSheetHeader
@@ -73,7 +75,9 @@ function BalanceSheet({
<LoadingIndicator loading={fetchHook.pending}>
<BalanceSheetTable
balanceSheet={balanceSheet}
balanceSheetIndex={balanceSheetIndex} />
balanceSheetIndex={balanceSheetIndex}
onFetchData={handleFetchData}
asDate={new Date()} />
</LoadingIndicator>
</div>
</div>

View File

@@ -11,6 +11,7 @@ import {
HTMLSelect,
Intent,
Popover,
Classes,
} from "@blueprintjs/core";
import {Select} from '@blueprintjs/select';
import {DateInput} from '@blueprintjs/datetime';
@@ -21,6 +22,7 @@ import {
parseDateRangeQuery,
} from 'utils';
import moment from 'moment';
import Icon from 'components/Icon';
export default function BalanceSheetHeader({
onSubmitFilter,
@@ -111,12 +113,16 @@ export default function BalanceSheetHeader({
</RadioGroup>
</div>
);
const infoIcon = useMemo(() => (<Icon icon="info-circle" iconSize={12} />), []);
return (
<FinancialStatementHeader>
<Row>
<Col sm={3}>
<FormGroup
label={intl.formatMessage({'id': 'report_date_range'})}
labelInfo={infoIcon}
minimal={true}
fill={true}>
@@ -131,6 +137,7 @@ export default function BalanceSheetHeader({
<Col sm={3}>
<FormGroup
label={intl.formatMessage({'id': 'from_date'})}
labelInfo={infoIcon}
minimal={true}
fill={true}>
@@ -146,6 +153,7 @@ export default function BalanceSheetHeader({
<Col sm={3}>
<FormGroup
label={intl.formatMessage({'id': 'to_date'})}
labelInfo={infoIcon}
minimal={true}
fill={true}>
@@ -163,7 +171,8 @@ export default function BalanceSheetHeader({
<Col sm={3}>
<FormGroup
label={'Display report columns'}
className="{'form-group-display-columns-by'}"
labelInfo={infoIcon}
className="form-group-display-columns-by form-group--select-list bp3-fill"
inline={false}>
<Select
@@ -184,6 +193,7 @@ export default function BalanceSheetHeader({
<Col sm={3}>
<FormGroup
label={'Show non-zero or active only'}
className="form-group--select-list bp3-fill"
inline={false}>
<Popover

View File

@@ -1,9 +1,10 @@
import React, {useMemo, useState, useEffect} from 'react';
import React, {useMemo, useState, useCallback, useEffect} from 'react';
import FinancialSheet from 'components/FinancialSheet';
import DataTable from 'components/DataTable';
import FinancialStatementConnect from 'connectors/FinancialStatements.connector';
import {compose} from 'utils';
import moment from 'moment';
import Money from 'components/Money';
function BalanceSheetTable({
balanceSheet,
@@ -14,25 +15,32 @@ function BalanceSheetTable({
getBalanceSheetLiabilitiesAccounts,
getBalanceSheetQuery,
}) {
const balanceSheetColumns = useMemo(() => {
return getBalanceSheetColumns(balanceSheetIndex);
}, [getBalanceSheetColumns]);
const balanceSheetQuery = useMemo(() => {
return getBalanceSheetQuery(balanceSheetIndex);
}, [getBalanceSheetQuery])
onFetchData,
asDate,
}) {
const balanceSheetColumns = useMemo(() =>
getBalanceSheetColumns(balanceSheetIndex),
[getBalanceSheetColumns, balanceSheetIndex]);
const balanceSheetQuery = useMemo(() =>
getBalanceSheetQuery(balanceSheetIndex),
[getBalanceSheetQuery, balanceSheetIndex])
const columns = useMemo(() => [
{
// Build our expander column
id: 'expander', // Make sure it has an ID
className: 'expander',
Header: ({
getToggleAllRowsExpandedProps,
isAllRowsExpanded
}) => (
<span {...getToggleAllRowsExpandedProps()}>
{isAllRowsExpanded ? '👇' : '👉'}
<span {...getToggleAllRowsExpandedProps()} className="toggle">
{isAllRowsExpanded ?
(<span class="arrow-down" />) :
(<span class="arrow-right" />)
}
</span>
),
Cell: ({ row }) =>
@@ -47,30 +55,41 @@ function BalanceSheetTable({
// of the row
paddingLeft: `${row.depth * 2}rem`,
},
className: 'toggle',
})}
>
{row.isExpanded ? '👇' : '👉'}
{row.isExpanded ?
(<span class="arrow-down" />) :
(<span class="arrow-right" />)
}
</span>
) : null,
width: 20,
disableResizing: true,
},
{
Header: 'Account Name',
accessor: 'name',
className: "actions",
className: "account_name",
},
{
Header: 'Code',
accessor: 'code',
className: "note",
className: "code",
},
...(balanceSheetQuery &&
balanceSheetQuery.display_columns_by === 'total') ? [
{
Header: 'Total',
accessor: 'balance.formatted_amount',
Cell: ({ cell }) => {
const row = cell.row.original;
if (!row.balance) { return ''; }
return (<Money amount={row.balance.formatted_amount} currency={'USD'} />);
},
className: "credit",
}
]: (balanceSheetColumns.map((column, index) => ({
] : (balanceSheetColumns.map((column, index) => ({
Header: column,
accessor: (row) => {
if (row.periods_balance && row.periods_balance[index]) {
@@ -87,33 +106,32 @@ function BalanceSheetTable({
setData([
{
name: 'Assets',
code: '',
children: [
...getBalanceSheetAssetsAccounts(balanceSheetIndex),
],
children: getBalanceSheetAssetsAccounts(balanceSheetIndex),
},
{
name: 'Liabilies & Equity',
code: '',
children: [
...getBalanceSheetLiabilitiesAccounts(balanceSheetIndex),
]
children: getBalanceSheetLiabilitiesAccounts(balanceSheetIndex),
}
])
}, [])
}, []);
const handleFetchData = useCallback(() => {
onFetchData && onFetchData();
}, [onFetchData]);
return (
<FinancialSheet
companyTitle={'Facebook, Incopration'}
sheetType={'Balance Sheet'}
date={''}>
date={asDate}>
<DataTable
className="bigcapital-datatable--financial-report"
columns={columns}
data={data} />
data={data}
onFetchData={handleFetchData} />
</FinancialSheet>
)
);
}
export default compose(

View File

@@ -1,8 +1,8 @@
import React, { useEffect, useState, useMemo } from 'react';
import React, { useEffect, useCallback, useState, useMemo } from 'react';
import TrialBalanceSheetHeader from "./TrialBalanceSheetHeader";
import LoadingIndicator from 'components/LoadingIndicator';
import TrialBalanceSheetTable from './TrialBalanceSheetTable';
import { useAsync } from 'react-use';
import useAsync from 'hooks/async';
import moment from 'moment';
import {compose} from 'utils';
import TrialBalanceSheetConnect from 'connectors/TrialBalanceSheet.connect';
@@ -13,44 +13,48 @@ function TrialBalanceSheet({
fetchTrialBalanceSheet,
getTrialBalanceSheetIndex,
getTrialBalanceAccounts,
trialBalanceSheetLoading,
}) {
const [filter, setFilter] = useState({
from_date: moment().startOf('year').format('YYYY-MM-DD'),
to_date: moment().endOf('year').format('YYYY-MM-DD'),
basis: 'cash',
basis: 'accural',
none_zero: false,
});
const [reload, setReload] = useState(false);
const fetchHook = useAsync(async () => {
await Promise.all([
fetchTrialBalanceSheet(),
const fetchHook = useAsync((query = filter) => {
return Promise.all([
fetchTrialBalanceSheet(query),
]);
});
}, false);
// handle fetch data of trial balance table.
const handleFetchData = useCallback(() => { fetchHook.execute() }, [fetchHook]);
// Retrieve balance sheet index by the given filter query.
const trialBalanceSheetIndex = useMemo(() => {
return getTrialBalanceSheetIndex(filter);
}, [getTrialBalanceSheetIndex, filter]);
const trialBalanceSheetIndex = useMemo(() =>
getTrialBalanceSheetIndex(filter),
[getTrialBalanceSheetIndex, filter]);
// Retrieve balance sheet accounts bu the given sheet index.
const trialBalanceAccounts = useMemo(() => {
return getTrialBalanceAccounts(trialBalanceSheetIndex);
}, [trialBalanceSheetIndex]);
const trialBalanceAccounts = useMemo(() =>
getTrialBalanceAccounts(trialBalanceSheetIndex),
[getTrialBalanceAccounts, trialBalanceSheetIndex]);
// Change page title of the dashboard.
useEffect(() => {
changePageTitle('Trial Balance Sheet');
}, []);
const handleFilterSubmit = (filter) => {
setFilter({
const handleFilterSubmit = useCallback((filter) => {
const parsedFilter = {
...filter,
from_date: moment(filter.from_date).format('YYYY-MM-DD'),
to_date: moment(filter.to_date).format('YYYY-MM-DD'),
});
setReload(true);
};
};
setFilter(parsedFilter);
fetchHook.execute(parsedFilter);
}, [setFilter, fetchHook]);
return (
<div class="financial-statement">
@@ -59,11 +63,11 @@ function TrialBalanceSheet({
onSubmitFilter={handleFilterSubmit} />
<div class="financial-statement__body">
<LoadingIndicator loading={fetchHook.pending}>
<TrialBalanceSheetTable
trialBalanceSheetAccounts={trialBalanceAccounts}
trialBalanceSheetIndex={trialBalanceSheetIndex} />
</LoadingIndicator>
<TrialBalanceSheetTable
trialBalanceSheetAccounts={trialBalanceAccounts}
trialBalanceSheetIndex={trialBalanceSheetIndex}
onFetchData={handleFetchData}
loading={trialBalanceSheetLoading} />
</div>
</div>
)

View File

@@ -1,4 +1,4 @@
import React, {useState} from 'react';
import React, {useState, useCallback} from 'react';
import FinancialStatementHeader from 'containers/Dashboard/FinancialStatements/FinancialStatementHeader';
import {Row, Col} from 'react-grid-system';
import {
@@ -48,7 +48,7 @@ export default function TrialBalanceSheetHeader({
setFilterByKey(name, date);
};
const handleSubmitClick = () => { onSubmitFilter(filter); };
const handleSubmitClick = useCallback(() => { onSubmitFilter(filter); }, [filter]);
return (
<FinancialStatementHeader>

View File

@@ -1,11 +1,13 @@
import React, {useEffect, useState, useMemo} from 'react';
import React, {useEffect, useState, useCallback, useMemo} from 'react';
import FinancialSheet from 'components/FinancialSheet';
import DataTable from 'components/DataTable';
import Money from 'components/Money';
export default function TrialBalanceSheetTable({
trialBalanceSheetAccounts,
trialBalanceSheetIndex,
onFetchData,
loading,
}) {
const [data, setData] = useState([]);
@@ -13,12 +15,16 @@ export default function TrialBalanceSheetTable({
{
// Build our expander column
id: 'expander', // Make sure it has an ID
className: 'expander',
Header: ({
getToggleAllRowsExpandedProps,
isAllRowsExpanded
}) => (
<span {...getToggleAllRowsExpandedProps()}>
{isAllRowsExpanded ? '👇' : '👉'}
<span {...getToggleAllRowsExpandedProps()} className="toggle">
{isAllRowsExpanded ?
(<span class="arrow-down" />) :
(<span class="arrow-right" />)
}
</span>
),
Cell: ({ row }) =>
@@ -33,48 +39,66 @@ export default function TrialBalanceSheetTable({
// of the row
paddingLeft: `${row.depth * 2}rem`,
},
className: 'toggle',
})}
>
{row.isExpanded ? '👇' : '👉'}
{row.isExpanded ?
(<span class="arrow-down" />) :
(<span class="arrow-right" />)
}
</span>
) : null,
width: 20,
disableResizing: true,
},
{
Header: 'Account Name',
accessor: 'name',
className: "actions",
className: "name",
},
{
Header: 'Code',
accessor: 'code',
className: "note",
className: "code",
width: 120,
},
{
Header: 'Credit',
accessor: 'credit',
accessor: r => (<Money amount={r.credit} currency="USD" />),
className: 'credit',
width: 120,
},
{
Header: 'debit',
accessor: 'debit',
Header: 'Debit',
accessor: r => (<Money amount={r.debit} currency="USD" />),
className: 'debit',
width: 120,
},
{
Header: 'Balance',
accessor: 'balance',
accessor: r => (<Money amount={r.balance} currency="USD" />),
className: 'balance',
width: 120,
}
], []);
const handleFetchData = useCallback(() => {
onFetchData && onFetchData();
}, [onFetchData]);
return (
<FinancialSheet
companyTitle={'Facebook, Incopration'}
sheetType={'Trial Balance Sheet'}
date={''}>
date={new Date()}
name="trial-balance"
loading={loading}>
<DataTable
className="bigcapital-datatable--financial-report"
columns={columns}
data={trialBalanceSheetAccounts} />
data={trialBalanceSheetAccounts}
onFetchData={handleFetchData} />
</FinancialSheet>
);
}