mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-20 14:50:32 +00:00
refactor(webapp): AR/AP aging summary table columns
This commit is contained in:
@@ -12,8 +12,13 @@ import {
|
|||||||
import { tableRowMapper } from '@/utils';
|
import { tableRowMapper } from '@/utils';
|
||||||
import AgingReport from './AgingReport';
|
import AgingReport from './AgingReport';
|
||||||
import { AgingSummaryRowType } from './_constants';
|
import { AgingSummaryRowType } from './_constants';
|
||||||
|
import { FinancialTable } from '../FinancialTable';
|
||||||
|
import { FinancialSheetStructure } from '../FinancialSheetStructure';
|
||||||
|
|
||||||
export default abstract class AgingSummaryTable extends AgingReport {
|
export default abstract class AgingSummaryTable extends R.compose(
|
||||||
|
FinancialSheetStructure,
|
||||||
|
FinancialTable
|
||||||
|
)(AgingReport) {
|
||||||
protected readonly report: IAgingSummaryData;
|
protected readonly report: IAgingSummaryData;
|
||||||
protected readonly query: IAgingSummaryQuery;
|
protected readonly query: IAgingSummaryQuery;
|
||||||
protected readonly agingPeriods: IAgingPeriod[];
|
protected readonly agingPeriods: IAgingPeriod[];
|
||||||
@@ -193,11 +198,11 @@ export default abstract class AgingSummaryTable extends AgingReport {
|
|||||||
* @returns {ITableColumn}
|
* @returns {ITableColumn}
|
||||||
*/
|
*/
|
||||||
public tableColumns = (): ITableColumn[] => {
|
public tableColumns = (): ITableColumn[] => {
|
||||||
return [
|
return R.compose(this.tableColumnsCellIndexing)([
|
||||||
this.contactNameTableColumn(),
|
this.contactNameTableColumn(),
|
||||||
{ label: 'Current', key: 'current' },
|
{ label: 'Current', key: 'current' },
|
||||||
...this.agingTableColumns(),
|
...this.agingTableColumns(),
|
||||||
{ label: 'Total', key: 'total' },
|
{ label: 'Total', key: 'total' },
|
||||||
];
|
]);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export const FinancialTable = (Base) =>
|
|||||||
* @param {ITableColumn[]} columns
|
* @param {ITableColumn[]} columns
|
||||||
* @returns {ITableColumn[]}
|
* @returns {ITableColumn[]}
|
||||||
*/
|
*/
|
||||||
protected tableColumnsCellIndexing = (
|
public tableColumnsCellIndexing = (
|
||||||
columns: ITableColumn[]
|
columns: ITableColumn[]
|
||||||
): ITableColumn[] => {
|
): ITableColumn[] => {
|
||||||
const cellIndex = increment(-1);
|
const cellIndex = increment(-1);
|
||||||
|
|||||||
@@ -18,11 +18,11 @@ function APAgingSummaryBodyJSX({
|
|||||||
// #withCurrentOrganization
|
// #withCurrentOrganization
|
||||||
organizationName,
|
organizationName,
|
||||||
}) {
|
}) {
|
||||||
const { isLoading } = useAPAgingSummaryContext();
|
const { isAPAgingLoading } = useAPAgingSummaryContext();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FinancialReportBody>
|
<FinancialReportBody>
|
||||||
{isLoading ? (
|
{isAPAgingLoading ? (
|
||||||
<FinancialSheetSkeleton />
|
<FinancialSheetSkeleton />
|
||||||
) : (
|
) : (
|
||||||
<APAgingSummaryTable organizationName={organizationName} />
|
<APAgingSummaryTable organizationName={organizationName} />
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export default function APAgingSummaryTable({
|
|||||||
}) {
|
}) {
|
||||||
// AP aging summary report content.
|
// AP aging summary report content.
|
||||||
const {
|
const {
|
||||||
APAgingSummary: { tableRows },
|
APAgingSummary: { table },
|
||||||
isAPAgingLoading,
|
isAPAgingLoading,
|
||||||
} = useAPAgingSummaryContext();
|
} = useAPAgingSummaryContext();
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ export default function APAgingSummaryTable({
|
|||||||
>
|
>
|
||||||
<APAgingSummaryDataTable
|
<APAgingSummaryDataTable
|
||||||
columns={columns}
|
columns={columns}
|
||||||
data={tableRows}
|
data={table.rows}
|
||||||
rowClassNames={tableRowTypesToClassnames}
|
rowClassNames={tableRowTypesToClassnames}
|
||||||
noInitialFetch={true}
|
noInitialFetch={true}
|
||||||
sticky={true}
|
sticky={true}
|
||||||
@@ -54,6 +54,24 @@ const APAgingSummaryDataTable = styled(ReportDataTable)`
|
|||||||
padding-top: 0.32rem;
|
padding-top: 0.32rem;
|
||||||
padding-bottom: 0.32rem;
|
padding-bottom: 0.32rem;
|
||||||
}
|
}
|
||||||
|
&:not(.no-results) {
|
||||||
|
.td {
|
||||||
|
border-bottom: 0;
|
||||||
|
padding-top: 0.4rem;
|
||||||
|
padding-bottom: 0.4rem;
|
||||||
|
}
|
||||||
|
&:not(:first-child) .td {
|
||||||
|
border-top: 1px solid transparent;
|
||||||
|
}
|
||||||
|
&.row_type--total {
|
||||||
|
font-weight: 500;
|
||||||
|
|
||||||
|
.td {
|
||||||
|
border-top: 1px solid #bbb;
|
||||||
|
border-bottom: 3px double #333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -1,59 +1,72 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import intl from 'react-intl-universal';
|
import intl from 'react-intl-universal';
|
||||||
|
import * as R from 'ramda';
|
||||||
|
|
||||||
import { If, FormattedMessage as T } from '@/components';
|
import { If, FormattedMessage as T } from '@/components';
|
||||||
import { useAPAgingSummaryContext } from './APAgingSummaryProvider';
|
import { useAPAgingSummaryContext } from './APAgingSummaryProvider';
|
||||||
import { getColumnWidth } from '@/utils';
|
|
||||||
import FinancialLoadingBar from '../FinancialLoadingBar';
|
import FinancialLoadingBar from '../FinancialLoadingBar';
|
||||||
|
import { agingSummaryDynamicColumns } from '../AgingSummary/dynamicColumns';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve AP aging summary columns.
|
* Retrieve AP aging summary columns.
|
||||||
*/
|
*/
|
||||||
export const useAPAgingSummaryColumns = () => {
|
export const useAPAgingSummaryColumns = () => {
|
||||||
const {
|
const {
|
||||||
APAgingSummary: { tableRows, columns },
|
APAgingSummary: { table },
|
||||||
} = useAPAgingSummaryContext();
|
} = useAPAgingSummaryContext();
|
||||||
|
|
||||||
const agingColumns = React.useMemo(() => {
|
return agingSummaryDynamicColumns(table.columns, table.rows);
|
||||||
return columns.map(
|
|
||||||
(agingColumn) =>
|
|
||||||
`${agingColumn.before_days} - ${
|
|
||||||
agingColumn.to_days || intl.get('and_over')
|
|
||||||
}`,
|
|
||||||
);
|
|
||||||
}, [columns]);
|
|
||||||
|
|
||||||
return useMemo(
|
|
||||||
() => [
|
|
||||||
{
|
|
||||||
Header: <T id={'vendor_name'} />,
|
|
||||||
accessor: 'name',
|
|
||||||
className: 'vendor_name',
|
|
||||||
width: 240,
|
|
||||||
sticky: 'left',
|
|
||||||
textOverview: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Header: <T id={'current'} />,
|
|
||||||
accessor: 'current',
|
|
||||||
className: 'current',
|
|
||||||
width: getColumnWidth(tableRows, `current`, { minWidth: 120 }),
|
|
||||||
},
|
|
||||||
...agingColumns.map((agingColumn, index) => ({
|
|
||||||
Header: agingColumn,
|
|
||||||
accessor: `aging-${index}`,
|
|
||||||
width: getColumnWidth(tableRows, `aging-${index}`, { minWidth: 120 }),
|
|
||||||
})),
|
|
||||||
{
|
|
||||||
Header: <T id={'total'} />,
|
|
||||||
accessor: 'total',
|
|
||||||
width: getColumnWidth(tableRows, 'total', { minWidth: 120 }),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[tableRows, agingColumns],
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve AP aging summary columns.
|
||||||
|
*/
|
||||||
|
// export const useAPAgingSummaryColumns = () => {
|
||||||
|
// const {
|
||||||
|
// APAgingSummary: { tableRows, columns },
|
||||||
|
// } = useAPAgingSummaryContext();
|
||||||
|
|
||||||
|
// const agingColumns = React.useMemo(() => {
|
||||||
|
// return columns.map(
|
||||||
|
// (agingColumn) =>
|
||||||
|
// `${agingColumn.before_days} - ${
|
||||||
|
// agingColumn.to_days || intl.get('and_over')
|
||||||
|
// }`,
|
||||||
|
// );
|
||||||
|
// }, [columns]);
|
||||||
|
|
||||||
|
// return useMemo(
|
||||||
|
// () => [
|
||||||
|
// {
|
||||||
|
// Header: <T id={'vendor_name'} />,
|
||||||
|
// accessor: 'name',
|
||||||
|
// className: 'vendor_name',
|
||||||
|
// width: 240,
|
||||||
|
// sticky: 'left',
|
||||||
|
// textOverview: true,
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// Header: <T id={'current'} />,
|
||||||
|
// accessor: 'current',
|
||||||
|
// className: 'current',
|
||||||
|
// width: getColumnWidth(tableRows, `current`, { minWidth: 120 }),
|
||||||
|
// },
|
||||||
|
// ...agingColumns.map((agingColumn, index) => ({
|
||||||
|
// Header: agingColumn,
|
||||||
|
// accessor: `aging-${index}`,
|
||||||
|
// width: getColumnWidth(tableRows, `aging-${index}`, { minWidth: 120 }),
|
||||||
|
// })),
|
||||||
|
// {
|
||||||
|
// Header: <T id={'total'} />,
|
||||||
|
// accessor: 'total',
|
||||||
|
// width: getColumnWidth(tableRows, 'total', { minWidth: 120 }),
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// [tableRows, agingColumns],
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A/P aging summary sheet loading bar.
|
* A/P aging summary sheet loading bar.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -19,7 +19,10 @@ export default function ReceivableAgingSummaryTable({
|
|||||||
organizationName,
|
organizationName,
|
||||||
}) {
|
}) {
|
||||||
// AR aging summary report context.
|
// AR aging summary report context.
|
||||||
const { ARAgingSummary, isARAgingLoading } = useARAgingSummaryContext();
|
const {
|
||||||
|
ARAgingSummary: { table },
|
||||||
|
isARAgingLoading,
|
||||||
|
} = useARAgingSummaryContext();
|
||||||
|
|
||||||
// AR aging summary columns.
|
// AR aging summary columns.
|
||||||
const columns = useARAgingSummaryColumns();
|
const columns = useARAgingSummaryColumns();
|
||||||
@@ -33,7 +36,7 @@ export default function ReceivableAgingSummaryTable({
|
|||||||
>
|
>
|
||||||
<ARAgingSummaryDataTable
|
<ARAgingSummaryDataTable
|
||||||
columns={columns}
|
columns={columns}
|
||||||
data={ARAgingSummary.tableRows}
|
data={table.rows}
|
||||||
rowClassNames={tableRowTypesToClassnames}
|
rowClassNames={tableRowTypesToClassnames}
|
||||||
noInitialFetch={true}
|
noInitialFetch={true}
|
||||||
sticky={true}
|
sticky={true}
|
||||||
|
|||||||
@@ -1,71 +1,20 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import intl from 'react-intl-universal';
|
|
||||||
|
|
||||||
import { useARAgingSummaryContext } from './ARAgingSummaryProvider';
|
import { useARAgingSummaryContext } from './ARAgingSummaryProvider';
|
||||||
import { If, FormattedMessage as T } from '@/components';
|
import { If, FormattedMessage as T } from '@/components';
|
||||||
import { getColumnWidth } from '@/utils';
|
|
||||||
import { Align } from '@/constants';
|
|
||||||
|
|
||||||
import FinancialLoadingBar from '../FinancialLoadingBar';
|
import FinancialLoadingBar from '../FinancialLoadingBar';
|
||||||
|
import { agingSummaryDynamicColumns } from '../AgingSummary/dynamicColumns';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve AR aging summary columns.
|
* Retrieve AR aging summary columns.
|
||||||
*/
|
*/
|
||||||
export const useARAgingSummaryColumns = () => {
|
export const useARAgingSummaryColumns = () => {
|
||||||
const {
|
const {
|
||||||
ARAgingSummary: { tableRows, columns },
|
ARAgingSummary: { table },
|
||||||
} = useARAgingSummaryContext();
|
} = useARAgingSummaryContext();
|
||||||
|
|
||||||
const agingColumns = React.useMemo(() => {
|
return agingSummaryDynamicColumns(table.columns, table.rows);
|
||||||
return columns.map(
|
|
||||||
(agingColumn) =>
|
|
||||||
`${agingColumn.before_days} - ${
|
|
||||||
agingColumn.to_days || intl.get('and_over')
|
|
||||||
}`,
|
|
||||||
);
|
|
||||||
}, [columns]);
|
|
||||||
|
|
||||||
return React.useMemo(
|
|
||||||
() => [
|
|
||||||
{
|
|
||||||
Header: <T id={'customer_name'} />,
|
|
||||||
accessor: 'name',
|
|
||||||
className: 'customer_name',
|
|
||||||
sticky: 'left',
|
|
||||||
width: 240,
|
|
||||||
textOverview: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Header: <T id={'current'} />,
|
|
||||||
accessor: 'current',
|
|
||||||
className: 'current',
|
|
||||||
width: getColumnWidth(tableRows, `current`, {
|
|
||||||
minWidth: 120,
|
|
||||||
}),
|
|
||||||
align: Align.Right
|
|
||||||
},
|
|
||||||
...agingColumns.map((agingColumn, index) => ({
|
|
||||||
Header: agingColumn,
|
|
||||||
accessor: `aging-${index}`,
|
|
||||||
width: getColumnWidth(tableRows, `aging-${index}`, {
|
|
||||||
minWidth: 120,
|
|
||||||
}),
|
|
||||||
align: Align.Right
|
|
||||||
})),
|
|
||||||
{
|
|
||||||
Header: <T id={'total'} />,
|
|
||||||
id: 'total',
|
|
||||||
accessor: 'total',
|
|
||||||
className: 'total',
|
|
||||||
width: getColumnWidth(tableRows, 'total', {
|
|
||||||
minWidth: 120,
|
|
||||||
}),
|
|
||||||
align: Align.Right
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[tableRows, agingColumns],
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import React, { useMemo } from 'react';
|
||||||
|
import * as R from 'ramda';
|
||||||
|
import { getColumnWidth } from '@/utils';
|
||||||
|
import { Align } from '@/constants';
|
||||||
|
|
||||||
|
const getTableCellValueAccessor = (index) => `cells[${index}].value`;
|
||||||
|
|
||||||
|
const contactNameAccessor = R.curry((data, column) => ({
|
||||||
|
key: column.key,
|
||||||
|
Header: column.label,
|
||||||
|
accessor: getTableCellValueAccessor(column.cell_index),
|
||||||
|
sticky: 'left',
|
||||||
|
width: 240,
|
||||||
|
textOverview: true,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const currentAccessor = R.curry((data, column) => {
|
||||||
|
const accessor = getTableCellValueAccessor(column.cell_index);
|
||||||
|
|
||||||
|
return {
|
||||||
|
key: column.key,
|
||||||
|
Header: column.label,
|
||||||
|
accessor,
|
||||||
|
className: column.id,
|
||||||
|
width: getColumnWidth(data, accessor, { minWidth: 120 }),
|
||||||
|
align: Align.Right,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const totalAccessor = R.curry((data, column) => {
|
||||||
|
const accessor = getTableCellValueAccessor(column.cell_index);
|
||||||
|
|
||||||
|
return {
|
||||||
|
Header: column.label,
|
||||||
|
id: column.key,
|
||||||
|
accessor: getTableCellValueAccessor(column.cell_index),
|
||||||
|
className: column.key,
|
||||||
|
width: getColumnWidth(data, accessor, { minWidth: 120 }),
|
||||||
|
align: Align.Right,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const agingPeriodAccessor = R.curry((data, column) => {
|
||||||
|
const accessor = getTableCellValueAccessor(column.cell_index);
|
||||||
|
|
||||||
|
return {
|
||||||
|
Header: column.label,
|
||||||
|
id: `${column.key}-${column.cell_index}`,
|
||||||
|
accessor,
|
||||||
|
className: column.key,
|
||||||
|
width: getColumnWidth(data, accessor, { minWidth: 120 }),
|
||||||
|
align: Align.Right,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const dynamicColumnMapper = R.curry((data, column) => {
|
||||||
|
const totalAccessorColumn = totalAccessor(data);
|
||||||
|
const currentAccessorColumn = currentAccessor(data);
|
||||||
|
const customerNameAccessorColumn = contactNameAccessor(data);
|
||||||
|
const agingPeriodAccessorColumn = agingPeriodAccessor(data);
|
||||||
|
|
||||||
|
return R.compose(
|
||||||
|
R.when(R.pathEq(['key'], 'total'), totalAccessorColumn),
|
||||||
|
R.when(R.pathEq(['key'], 'current'), currentAccessorColumn),
|
||||||
|
R.when(R.pathEq(['key'], 'customer_name'), customerNameAccessorColumn),
|
||||||
|
R.when(R.pathEq(['key'], 'vendor_name'), customerNameAccessorColumn),
|
||||||
|
R.when(R.pathEq(['key'], 'aging_period'), agingPeriodAccessorColumn),
|
||||||
|
)(column);
|
||||||
|
});
|
||||||
|
|
||||||
|
export const agingSummaryDynamicColumns = (columns, data) => {
|
||||||
|
return R.map(dynamicColumnMapper(data), columns);
|
||||||
|
};
|
||||||
@@ -138,26 +138,12 @@ export function useARAgingSummaryReport(query, props) {
|
|||||||
method: 'get',
|
method: 'get',
|
||||||
url: '/financial_statements/receivable_aging_summary',
|
url: '/financial_statements/receivable_aging_summary',
|
||||||
params: query,
|
params: query,
|
||||||
|
headers: {
|
||||||
|
Accept: 'application/json+table',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
select: (res) => ({
|
select: (res) => res.data,
|
||||||
columns: res.data.columns,
|
|
||||||
data: res.data.data,
|
|
||||||
query: res.data.query,
|
|
||||||
tableRows: ARAgingSummaryTableRowsMapper({
|
|
||||||
customers: res.data.data.customers,
|
|
||||||
total: res.data.data.total,
|
|
||||||
columns: res.data.columns,
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
defaultData: {
|
|
||||||
data: {
|
|
||||||
customers: [],
|
|
||||||
total: {},
|
|
||||||
},
|
|
||||||
columns: [],
|
|
||||||
tableRows: [],
|
|
||||||
},
|
|
||||||
...props,
|
...props,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -173,26 +159,12 @@ export function useAPAgingSummaryReport(query, props) {
|
|||||||
method: 'get',
|
method: 'get',
|
||||||
url: '/financial_statements/payable_aging_summary',
|
url: '/financial_statements/payable_aging_summary',
|
||||||
params: query,
|
params: query,
|
||||||
|
headers: {
|
||||||
|
Accept: 'application/json+table',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
select: (res) => ({
|
select: (res) => res.data,
|
||||||
columns: res.data.columns,
|
|
||||||
data: res.data.data,
|
|
||||||
query: res.data.query,
|
|
||||||
tableRows: APAgingSummaryTableRowsMapper({
|
|
||||||
vendors: res.data.data.vendors,
|
|
||||||
total: res.data.data.total,
|
|
||||||
columns: res.data.columns,
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
defaultData: {
|
|
||||||
data: {
|
|
||||||
vendors: [],
|
|
||||||
total: {},
|
|
||||||
},
|
|
||||||
columns: [],
|
|
||||||
tableRows: [],
|
|
||||||
},
|
|
||||||
...props,
|
...props,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user