mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-18 22:00:31 +00:00
refactoring: APAing summary.
This commit is contained in:
@@ -4,65 +4,65 @@ import { omit } from 'lodash';
|
||||
import MultiSelect from 'components/MultiSelect';
|
||||
import { FormattedMessage as T } from 'react-intl';
|
||||
|
||||
export default function CustomersMultiSelect({
|
||||
customers,
|
||||
export default function ContactsMultiSelect({
|
||||
contacts,
|
||||
defaultText = <T id={'all_customers'} />,
|
||||
buttonProps,
|
||||
|
||||
onCustomerSelected,
|
||||
onCustomerSelected: onContactSelected,
|
||||
...selectProps
|
||||
}) {
|
||||
const [selectedCustomers, setSelectedCustomers] = useState({});
|
||||
const [selectedContacts, setSelectedContacts] = useState({});
|
||||
|
||||
const isCustomerSelect = useCallback(
|
||||
(id) => typeof selectedCustomers[id] !== 'undefined',
|
||||
[selectedCustomers],
|
||||
const isContactSelect = useCallback(
|
||||
(id) => typeof selectedContacts[id] !== 'undefined',
|
||||
[selectedContacts],
|
||||
);
|
||||
|
||||
const customerRenderer = useCallback(
|
||||
(customer, { handleClick }) => (
|
||||
const contactRenderer = useCallback(
|
||||
(contact, { handleClick }) => (
|
||||
<MenuItem
|
||||
icon={isCustomerSelect(customer.id) ? 'tick' : 'blank'}
|
||||
text={customer.display_name}
|
||||
key={customer.id}
|
||||
icon={isContactSelect(contact.id) ? 'tick' : 'blank'}
|
||||
text={contact.display_name}
|
||||
key={contact.id}
|
||||
onClick={handleClick}
|
||||
/>
|
||||
),
|
||||
[isCustomerSelect],
|
||||
[isContactSelect],
|
||||
);
|
||||
|
||||
const countSelected = useMemo(() => Object.values(selectedCustomers).length, [
|
||||
selectedCustomers,
|
||||
const countSelected = useMemo(() => Object.values(selectedContacts).length, [
|
||||
selectedContacts,
|
||||
]);
|
||||
|
||||
const onContactSelect = useCallback(
|
||||
({ id }) => {
|
||||
const selected = {
|
||||
...(isCustomerSelect(id)
|
||||
...(isContactSelect(id)
|
||||
? {
|
||||
...omit(selectedCustomers, [id]),
|
||||
...omit(selectedContacts, [id]),
|
||||
}
|
||||
: {
|
||||
...selectedCustomers,
|
||||
...selectedContacts,
|
||||
[id]: true,
|
||||
}),
|
||||
};
|
||||
setSelectedCustomers({ ...selected });
|
||||
onCustomerSelected && onCustomerSelected(selected);
|
||||
setSelectedContacts({ ...selected });
|
||||
onContactSelected && onContactSelected(selected);
|
||||
},
|
||||
[
|
||||
setSelectedCustomers,
|
||||
selectedCustomers,
|
||||
isCustomerSelect,
|
||||
onCustomerSelected,
|
||||
setSelectedContacts,
|
||||
selectedContacts,
|
||||
isContactSelect,
|
||||
onContactSelected,
|
||||
],
|
||||
);
|
||||
|
||||
return (
|
||||
<MultiSelect
|
||||
items={customers}
|
||||
items={contacts}
|
||||
noResults={<MenuItem disabled={true} text="No results." />}
|
||||
itemRenderer={customerRenderer}
|
||||
itemRenderer={contactRenderer}
|
||||
popoverProps={{ minimal: true }}
|
||||
filterable={true}
|
||||
onItemSelect={onContactSelect}
|
||||
@@ -43,7 +43,7 @@ import DashboardCard from './Dashboard/DashboardCard';
|
||||
import InputPrependText from './Forms/InputPrependText';
|
||||
import PageFormBigNumber from './PageFormBigNumber';
|
||||
import AccountsMultiSelect from './AccountsMultiSelect';
|
||||
import CustomersMultiSelect from './CustomersMultiSelect';
|
||||
import ContactsMultiSelect from './ContactsMultiSelect';
|
||||
import Skeleton from './Skeleton'
|
||||
import ContextMenu from './ContextMenu'
|
||||
import TableFastCell from './Datatable/TableFastCell';
|
||||
@@ -99,7 +99,7 @@ export {
|
||||
PageFormBigNumber,
|
||||
AccountsMultiSelect,
|
||||
DataTableEditable,
|
||||
CustomersMultiSelect,
|
||||
ContactsMultiSelect,
|
||||
TableFastCell,
|
||||
Skeleton,
|
||||
ContextMenu,
|
||||
|
||||
@@ -1,110 +1,60 @@
|
||||
import React, { useEffect, useState, useCallback } from 'react';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { queryCache, useQuery } from 'react-query';
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import moment from 'moment';
|
||||
|
||||
import 'style/pages/FinancialStatements/ARAgingSummary.scss';
|
||||
|
||||
import { FinancialStatement } from 'components';
|
||||
|
||||
import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
||||
import DashboardPageContent from 'components/Dashboard/DashboardPageContent';
|
||||
|
||||
import APAgingSummaryActionsBar from './APAgingSummaryActionsBar';
|
||||
import APAgingSummaryHeader from './APAgingSummaryHeader';
|
||||
import APAgingSummaryActionsBar from './APAgingSummaryActionsBar';
|
||||
import APAgingSummaryTable from './APAgingSummaryTable';
|
||||
import DashboardPageContent from 'components/Dashboard/DashboardPageContent';
|
||||
import { APAgingSummaryProvider } from './APAgingSummaryProvider';
|
||||
|
||||
import withSettings from 'containers/Settings/withSettings';
|
||||
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||
import withAPAgingSummaryActions from './withAPAgingSummaryActions';
|
||||
import withAPAgingSummary from './withAPAgingSummary';
|
||||
import { transformFilterFormToQuery } from './common';
|
||||
|
||||
import { compose } from 'utils';
|
||||
|
||||
import 'style/pages/FinancialStatements/ARAgingSummary.scss';
|
||||
|
||||
/**
|
||||
* AP aging summary report.
|
||||
*/
|
||||
function APAgingSummary({
|
||||
// #withSettings
|
||||
organizationName,
|
||||
|
||||
// #withDashboardActions
|
||||
changePageTitle,
|
||||
setDashboardBackLink,
|
||||
|
||||
// #withAPAgingSummary
|
||||
APAgingSummaryRefresh,
|
||||
|
||||
// #withAPAgingSummaryActions
|
||||
requestPayableAgingSummary,
|
||||
refreshAPAgingSummary,
|
||||
toggleFilterAPAgingSummary,
|
||||
}) {
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
const [query, setQuery] = useState({
|
||||
const [filter, setFilter] = useState({
|
||||
asDate: moment().endOf('day').format('YYYY-MM-DD'),
|
||||
agingBeforeDays: 30,
|
||||
agingPeriods: 3,
|
||||
});
|
||||
|
||||
// handle fetching payable aging summary report.
|
||||
const fetchAPAgingSummarySheet = useQuery(
|
||||
['payable-aging-summary', query],
|
||||
(key, _query) =>
|
||||
requestPayableAgingSummary({
|
||||
...transformFilterFormToQuery(_query),
|
||||
}),
|
||||
{ enable: true },
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
changePageTitle(formatMessage({ id: 'payable_aging_summary' }));
|
||||
}, [changePageTitle, formatMessage]);
|
||||
|
||||
useEffect(() => {
|
||||
if (APAgingSummaryRefresh) {
|
||||
queryCache.invalidateQueries('payable-aging-summary');
|
||||
refreshAPAgingSummary(false);
|
||||
}
|
||||
}, [APAgingSummaryRefresh, refreshAPAgingSummary]);
|
||||
|
||||
useEffect(() => {
|
||||
setDashboardBackLink(true);
|
||||
return () => {
|
||||
setDashboardBackLink(false);
|
||||
};
|
||||
}, [setDashboardBackLink]);
|
||||
|
||||
const handleFilterSubmit = (filter) => {
|
||||
// Handle filter submit.
|
||||
const handleFilterSubmit = useCallback((filter) => {
|
||||
const _filter = {
|
||||
...filter,
|
||||
asDate: moment(filter.asDate).format('YYYY-MM-DD'),
|
||||
};
|
||||
setQuery(_filter);
|
||||
refreshAPAgingSummary(true);
|
||||
toggleFilterAPAgingSummary(false);
|
||||
};
|
||||
setFilter(_filter);
|
||||
}, []);
|
||||
|
||||
// Handle number format submit.
|
||||
const handleNumberFormatSubmit = (numberFormat) => {
|
||||
setQuery({
|
||||
...query,
|
||||
setFilter({
|
||||
...filter,
|
||||
numberFormat,
|
||||
});
|
||||
refreshAPAgingSummary(true);
|
||||
};
|
||||
|
||||
return (
|
||||
<DashboardInsider>
|
||||
<APAgingSummaryProvider filter={filter}>
|
||||
<APAgingSummaryActionsBar
|
||||
numberFormat={query.numberFormat}
|
||||
numberFormat={filter.numberFormat}
|
||||
onNumberFormatSubmit={handleNumberFormatSubmit}
|
||||
/>
|
||||
<DashboardPageContent>
|
||||
<FinancialStatement>
|
||||
<APAgingSummaryHeader
|
||||
pageFilter={query}
|
||||
pageFilter={filter}
|
||||
onSubmitFilter={handleFilterSubmit}
|
||||
/>
|
||||
<div className={'financial-statement__body'}>
|
||||
@@ -112,17 +62,12 @@ function APAgingSummary({
|
||||
</div>
|
||||
</FinancialStatement>
|
||||
</DashboardPageContent>
|
||||
</DashboardInsider>
|
||||
</APAgingSummaryProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withDashboardActions,
|
||||
withAPAgingSummaryActions,
|
||||
withSettings(({ organizationSettings }) => ({
|
||||
organizationName: organizationSettings.name,
|
||||
})),
|
||||
withAPAgingSummary(({ APAgingSummaryRefresh }) => ({
|
||||
APAgingSummaryRefresh,
|
||||
organizationName: organizationSettings?.name,
|
||||
})),
|
||||
)(APAgingSummary);
|
||||
|
||||
@@ -8,7 +8,6 @@ import {
|
||||
PopoverInteractionKind,
|
||||
Position,
|
||||
} from '@blueprintjs/core';
|
||||
import { safeInvoke } from '@blueprintjs/core/lib/esm/common/utils';
|
||||
|
||||
import { FormattedMessage as T } from 'react-intl';
|
||||
import classNames from 'classnames';
|
||||
@@ -17,10 +16,11 @@ import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
|
||||
import { Icon } from 'components';
|
||||
import NumberFormatDropdown from 'components/NumberFormatDropdown';
|
||||
|
||||
import withAPAgingSummary from './withAPAgingSummary';
|
||||
import { useAPAgingSummaryContext } from './APAgingSummaryProvider';
|
||||
import withARAgingSummaryActions from './withAPAgingSummaryActions';
|
||||
|
||||
import { compose } from 'utils';
|
||||
import { safeInvoke } from '@blueprintjs/core/lib/esm/common/utils';
|
||||
|
||||
/**
|
||||
* AP Aging summary sheet - Actions bar.
|
||||
@@ -28,25 +28,25 @@ import { compose } from 'utils';
|
||||
function APAgingSummaryActionsBar({
|
||||
//#withPayableAgingSummary
|
||||
payableAgingFilter,
|
||||
payableAgingLoading,
|
||||
|
||||
//#withARAgingSummaryActions
|
||||
toggleFilterAPAgingSummary,
|
||||
refreshAPAgingSummary,
|
||||
|
||||
//#ownProps
|
||||
numberFormat,
|
||||
onNumberFormatSubmit,
|
||||
}) {
|
||||
const { isAPAgingFetching, refetch } = useAPAgingSummaryContext();
|
||||
|
||||
const handleFilterToggleClick = () => toggleFilterAPAgingSummary();
|
||||
|
||||
// handle recalculate report button.
|
||||
const handleRecalculateReport = () => refreshAPAgingSummary(true);
|
||||
const handleRecalculateReport = () => refetch();
|
||||
|
||||
// handle number format submit.
|
||||
const handleNumberFormatSubmit = (numberFormat) =>
|
||||
safeInvoke(onNumberFormatSubmit, numberFormat);
|
||||
|
||||
|
||||
return (
|
||||
<DashboardActionsBar>
|
||||
<NavbarGroup>
|
||||
@@ -76,7 +76,7 @@ function APAgingSummaryActionsBar({
|
||||
<NumberFormatDropdown
|
||||
numberFormat={numberFormat}
|
||||
onSubmit={handleNumberFormatSubmit}
|
||||
submitDisabled={payableAgingLoading}
|
||||
submitDisabled={isAPAgingFetching}
|
||||
/>
|
||||
}
|
||||
minimal={true}
|
||||
@@ -112,12 +112,4 @@ function APAgingSummaryActionsBar({
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withARAgingSummaryActions,
|
||||
withAPAgingSummary(
|
||||
({ payableAgingSummaryLoading, payableAgingSummaryFilter }) => ({
|
||||
payableAgingLoading: payableAgingSummaryLoading,
|
||||
payableAgingFilter: payableAgingSummaryFilter,
|
||||
}),
|
||||
),
|
||||
)(APAgingSummaryActionsBar);
|
||||
export default compose(withARAgingSummaryActions)(APAgingSummaryActionsBar);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { FormattedMessage as T } from 'react-intl';
|
||||
import { Formik, Form, validateYupSchema } from 'formik';
|
||||
import { Formik, Form } from 'formik';
|
||||
import * as Yup from 'yup';
|
||||
import moment from 'moment';
|
||||
import { Tabs, Tab, Button, Intent } from '@blueprintjs/core';
|
||||
@@ -48,11 +48,13 @@ function APAgingSummaryHeader({
|
||||
// handle form submit.
|
||||
const handleSubmit = (values, { setSubmitting }) => {
|
||||
onSubmitFilter(values);
|
||||
toggleFilterAPAgingSummary();
|
||||
setSubmitting(false);
|
||||
};
|
||||
|
||||
// handle cancel button click.
|
||||
const handleCancelClick = () => toggleFilterAPAgingSummary();
|
||||
|
||||
return (
|
||||
<FinancialStatementHeader isOpen={payableAgingFilter}>
|
||||
<Formik
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
import React from 'react';
|
||||
import { FastField } from 'formik';
|
||||
import { DateInput } from '@blueprintjs/datetime';
|
||||
import { Intent, FormGroup, InputGroup, Position } from '@blueprintjs/core';
|
||||
import {
|
||||
Intent,
|
||||
FormGroup,
|
||||
InputGroup,
|
||||
Position,
|
||||
Classes,
|
||||
} from '@blueprintjs/core';
|
||||
import { FormattedMessage as T } from 'react-intl';
|
||||
import { Row, Col, FieldHint } from 'components';
|
||||
import classNames from 'classnames';
|
||||
import { ContactsMultiSelect, Row, Col, FieldHint } from 'components';
|
||||
import { useAPAgingSummaryContext } from './APAgingSummaryProvider';
|
||||
import {
|
||||
momentFormatter,
|
||||
tansformDateValue,
|
||||
@@ -15,6 +23,7 @@ import {
|
||||
* AP Aging Summary - Drawer Header - General Fields.
|
||||
*/
|
||||
export default function APAgingSummaryHeaderGeneral() {
|
||||
const { vendors } = useAPAgingSummaryContext();
|
||||
return (
|
||||
<div>
|
||||
<Row>
|
||||
@@ -72,6 +81,19 @@ export default function APAgingSummaryHeaderGeneral() {
|
||||
</FastField>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col xs={5}>
|
||||
<FormGroup
|
||||
label={<T id={'specific_vendors'} />}
|
||||
className={classNames('form-group--select-list', Classes.FILL)}
|
||||
>
|
||||
<ContactsMultiSelect
|
||||
defaultText={<T id={'all_vendors'} />}
|
||||
contacts={vendors}
|
||||
/>
|
||||
</FormGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
import React, { useMemo, createContext, useContext } from 'react';
|
||||
import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
||||
import { useAPAgingSummaryReport,useARAgingSummaryReport , useVendors } from 'hooks/query';
|
||||
import { transformFilterFormToQuery } from '../common';
|
||||
|
||||
const APAgingSummaryContext = createContext();
|
||||
|
||||
/**
|
||||
* A/P aging summary provider.
|
||||
*/
|
||||
function APAgingSummaryProvider({ filter, ...props }) {
|
||||
// Transformers the filter from to the Url query.
|
||||
const query = useMemo(() => transformFilterFormToQuery(filter), [filter]);
|
||||
|
||||
const {
|
||||
data: APAgingSummary,
|
||||
isLoading: isAPAgingLoading,
|
||||
isFetching: isAPAgingFetching,
|
||||
refetch,
|
||||
} = useAPAgingSummaryReport(query);
|
||||
|
||||
// Retrieve the vendors list.
|
||||
const {
|
||||
data: { vendors },
|
||||
isFetching: isVendorsLoading,
|
||||
} = useVendors();
|
||||
|
||||
const provider = {
|
||||
APAgingSummary,
|
||||
vendors,
|
||||
|
||||
isAPAgingLoading,
|
||||
isAPAgingFetching,
|
||||
isVendorsLoading,
|
||||
refetch,
|
||||
};
|
||||
|
||||
return (
|
||||
<DashboardInsider name={'AP-Aging-Summary'}>
|
||||
<APAgingSummaryContext.Provider value={provider} {...props} />
|
||||
</DashboardInsider>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
const useAPAgingSummaryContext = () => useContext(APAgingSummaryContext);
|
||||
|
||||
|
||||
export { APAgingSummaryProvider, useAPAgingSummaryContext };
|
||||
@@ -1,71 +1,29 @@
|
||||
import React, { useMemo, useCallback } from 'react';
|
||||
import React, { useCallback } from 'react';
|
||||
import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||
import { DataTable } from 'components';
|
||||
import FinancialSheet from 'components/FinancialSheet';
|
||||
|
||||
import withAPAgingSummary from './withAPAgingSummary';
|
||||
|
||||
import { compose, getColumnWidth } from 'utils';
|
||||
import { useAPAgingSummaryContext } from './APAgingSummaryProvider';
|
||||
import { useAPAgingSummaryColumns } from './components';
|
||||
|
||||
/**
|
||||
* AP aging summary table sheet.
|
||||
*/
|
||||
function APAgingSummaryTable({
|
||||
//#withPayableAgingSummary
|
||||
payableAgingColumns,
|
||||
payableAgingRows,
|
||||
payableAgingLoading,
|
||||
|
||||
export default function APAgingSummaryTable({
|
||||
//#ownProps
|
||||
organizationName,
|
||||
}) {
|
||||
const { formatMessage } = useIntl();
|
||||
const agingColumns = useMemo(
|
||||
() =>
|
||||
payableAgingColumns.map((agingColumn) => {
|
||||
return `${agingColumn.before_days} - ${
|
||||
agingColumn.to_days || 'And Over'
|
||||
}`;
|
||||
}),
|
||||
[payableAgingColumns],
|
||||
);
|
||||
|
||||
const columns = useMemo(
|
||||
() => [
|
||||
{
|
||||
Header: <T id={'vendor_name'} />,
|
||||
accessor: 'name',
|
||||
className: 'name',
|
||||
width: 240,
|
||||
sticky: 'left',
|
||||
textOverview: true,
|
||||
},
|
||||
{
|
||||
Header: <T id={'current'} />,
|
||||
accessor: 'current',
|
||||
className: 'current',
|
||||
width: getColumnWidth(payableAgingRows, `current`, {
|
||||
minWidth: 120,
|
||||
}),
|
||||
},
|
||||
// AP aging summary report content.
|
||||
const {
|
||||
APAgingSummary: { tableRows },
|
||||
isAPAgingFetching,
|
||||
} = useAPAgingSummaryContext();
|
||||
|
||||
// AP aging summary columns.
|
||||
const columns = useAPAgingSummaryColumns();
|
||||
|
||||
...agingColumns.map((agingColumn, index) => ({
|
||||
Header: agingColumn,
|
||||
accessor: `aging-${index}`,
|
||||
width: getColumnWidth(payableAgingRows, `aging-${index}`, {
|
||||
minWidth: 120,
|
||||
}),
|
||||
})),
|
||||
{
|
||||
Header: <T id={'total'} />,
|
||||
accessor: 'total',
|
||||
width: getColumnWidth(payableAgingRows, 'total', {
|
||||
minWidth: 120,
|
||||
}),
|
||||
},
|
||||
],
|
||||
[payableAgingRows],
|
||||
);
|
||||
const rowClassNames = (row) => [`row-type--${row.original.rowType}`];
|
||||
|
||||
return (
|
||||
@@ -74,12 +32,12 @@ function APAgingSummaryTable({
|
||||
name={'payable-aging-summary'}
|
||||
sheetType={formatMessage({ id: 'payable_aging_summary' })}
|
||||
asDate={new Date()}
|
||||
loading={payableAgingLoading}
|
||||
loading={isAPAgingFetching}
|
||||
>
|
||||
<DataTable
|
||||
className={'bigcapital-datatable--financial-report'}
|
||||
columns={columns}
|
||||
data={payableAgingRows}
|
||||
data={tableRows}
|
||||
rowClassNames={rowClassNames}
|
||||
noInitialFetch={true}
|
||||
sticky={true}
|
||||
@@ -87,17 +45,3 @@ function APAgingSummaryTable({
|
||||
</FinancialSheet>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withAPAgingSummary(
|
||||
({
|
||||
payableAgingSummaryLoading,
|
||||
payableAgingSummaryColumns,
|
||||
payableAgingSummaryRows,
|
||||
}) => ({
|
||||
payableAgingLoading: payableAgingSummaryLoading,
|
||||
payableAgingColumns: payableAgingSummaryColumns,
|
||||
payableAgingRows: payableAgingSummaryRows,
|
||||
}),
|
||||
),
|
||||
)(APAgingSummaryTable);
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import { useAPAgingSummaryContext } from './APAgingSummaryProvider';
|
||||
import { getColumnWidth } from 'utils';
|
||||
import { FormattedMessage as T } from 'react-intl';
|
||||
|
||||
/**
|
||||
* 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 || 'And Over'}`,
|
||||
);
|
||||
}, [columns]);
|
||||
|
||||
return useMemo(
|
||||
() => [
|
||||
{
|
||||
Header: <T id={'vendor_name'} />,
|
||||
accessor: 'name',
|
||||
className: '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],
|
||||
);
|
||||
};
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
} from '@blueprintjs/core';
|
||||
import { FormattedMessage as T } from 'react-intl';
|
||||
import classNames from 'classnames';
|
||||
import { CustomersMultiSelect, Row, Col, FieldHint } from 'components';
|
||||
import { ContactsMultiSelect, Row, Col, FieldHint } from 'components';
|
||||
import { momentFormatter } from 'utils';
|
||||
|
||||
import { useARAgingSummaryContext } from './ARAgingSummaryProvider';
|
||||
@@ -97,7 +97,7 @@ export default function ARAgingSummaryHeaderGeneral() {
|
||||
label={<T id={'specific_customers'} />}
|
||||
className={classNames('form-group--select-list', Classes.FILL)}
|
||||
>
|
||||
<CustomersMultiSelect customers={customers} />
|
||||
<ContactsMultiSelect contacts={customers} />
|
||||
</FormGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
@@ -261,3 +261,38 @@ export const ARAgingSummaryTableRowsMapper = (sheet, total) => {
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
export const APAgingSummaryTableRowsMapper = (sheet, total) => {
|
||||
const rows = [];
|
||||
|
||||
const mapAging = (agingPeriods) => {
|
||||
return agingPeriods.reduce((acc, aging, index) => {
|
||||
acc[`aging-${index}`] = aging.total.formatted_amount;
|
||||
return acc;
|
||||
}, {});
|
||||
};
|
||||
sheet.vendors.forEach((vendor) => {
|
||||
const agingRow = mapAging(vendor.aging);
|
||||
|
||||
rows.push({
|
||||
rowType: 'vendor',
|
||||
name: vendor.vendor_name,
|
||||
...agingRow,
|
||||
current: vendor.current.formatted_amount,
|
||||
total: vendor.total.formatted_amount,
|
||||
});
|
||||
});
|
||||
if (rows.length <= 0) {
|
||||
return [];
|
||||
}
|
||||
return [
|
||||
...rows,
|
||||
{
|
||||
name: '',
|
||||
rowType: 'total',
|
||||
current: sheet.total.current.formatted_amount,
|
||||
...mapAging(sheet.total.aging),
|
||||
total: sheet.total.total.formatted_amount,
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
@@ -6,10 +6,11 @@ import {
|
||||
profitLossSheetReducer,
|
||||
generalLedgerTableRowsReducer,
|
||||
journalTableRowsReducer,
|
||||
ARAgingSummaryTableRowsMapper
|
||||
ARAgingSummaryTableRowsMapper,
|
||||
APAgingSummaryTableRowsMapper
|
||||
} from 'containers/FinancialStatements/reducers';
|
||||
import useApiRequest from '../useRequest';
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve balance sheet.
|
||||
*/
|
||||
@@ -27,7 +28,7 @@ export function useBalanceSheet(query, props) {
|
||||
tableRows: balanceSheetRowsReducer(res.data.data),
|
||||
...res.data,
|
||||
}),
|
||||
...props
|
||||
...props,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -69,8 +70,8 @@ export function useTrialBalanceSheet(query, props) {
|
||||
tableRows: [],
|
||||
data: [],
|
||||
query: {},
|
||||
})
|
||||
}
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,7 +102,7 @@ export function useProfitLossSheet(query, props) {
|
||||
columns: [],
|
||||
query: {},
|
||||
}),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -132,7 +133,7 @@ export function useGeneralLedgerSheet(query, props) {
|
||||
data: {},
|
||||
query: {},
|
||||
}),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -143,12 +144,11 @@ export function useJournalSheet(query, props) {
|
||||
|
||||
const states = useQuery(
|
||||
['FINANCIAL-REPORT', 'JOURNAL', query],
|
||||
() =>
|
||||
apiRequest.get('/financial_statements/journal', { params: query }),
|
||||
() => apiRequest.get('/financial_statements/journal', { params: query }),
|
||||
{
|
||||
select: (res) => ({
|
||||
tableRows: journalTableRowsReducer(res.data.data),
|
||||
...res.data,
|
||||
...res.data,
|
||||
}),
|
||||
...props,
|
||||
},
|
||||
@@ -160,8 +160,8 @@ export function useJournalSheet(query, props) {
|
||||
data: {},
|
||||
tableRows: [],
|
||||
query: {},
|
||||
})
|
||||
}
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -185,7 +185,7 @@ export function useARAgingSummaryReport(query, props) {
|
||||
customers: res.data.data.customers,
|
||||
total: res.data.data.total,
|
||||
columns: res.data.columns,
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
initialData: {
|
||||
data: {
|
||||
@@ -194,11 +194,50 @@ export function useARAgingSummaryReport(query, props) {
|
||||
total: {},
|
||||
},
|
||||
columns: [],
|
||||
tableRows: []
|
||||
}
|
||||
tableRows: [],
|
||||
},
|
||||
},
|
||||
initialDataUpdatedAt: 0,
|
||||
...props
|
||||
...props,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve AP aging summary report.
|
||||
*/
|
||||
export function useAPAgingSummaryReport(query, props) {
|
||||
const apiRequest = useApiRequest();
|
||||
|
||||
return useQuery(
|
||||
['FINANCIAL-REPORT', 'AP-AGING-SUMMARY', query],
|
||||
() =>
|
||||
apiRequest.get('/financial_statements/payable_aging_summary', {
|
||||
params: query,
|
||||
}),
|
||||
{
|
||||
select: (res) => ({
|
||||
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,
|
||||
}),
|
||||
}),
|
||||
initialData: {
|
||||
data: {
|
||||
data: {
|
||||
vendors: [],
|
||||
total: {},
|
||||
},
|
||||
columns: [],
|
||||
tableRows: [],
|
||||
},
|
||||
},
|
||||
initialDataUpdatedAt: 0,
|
||||
...props,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -961,6 +961,7 @@ export default {
|
||||
adjustment_reasons: 'Adjustment reasons',
|
||||
specific_customers: 'Specific Customers',
|
||||
all_customers: 'All Customers',
|
||||
all_vendors: 'All Vendors',
|
||||
selected_customers: '{count} Selected Customers',
|
||||
transaction_number: 'Transaction #',
|
||||
running_balance: 'Running balance',
|
||||
@@ -976,4 +977,6 @@ export default {
|
||||
receipt_paper: 'Receipt Paper',
|
||||
payable_aging_summary: 'Payable Aging Summary',
|
||||
payment_receive_paper: 'Payment Receive Paper',
|
||||
specific_vendors: 'Specific Vendors',
|
||||
|
||||
};
|
||||
|
||||
@@ -155,13 +155,16 @@ export default [
|
||||
backLink: true,
|
||||
sidebarShrink: true,
|
||||
},
|
||||
// {
|
||||
// path: '/financial-reports/payable-aging-summary',
|
||||
// component: lazy(() =>
|
||||
// import('containers/FinancialStatements/APAgingSummary/APAgingSummary'),
|
||||
// ),
|
||||
// breadcrumb: 'Payable Aging Summary',
|
||||
// },
|
||||
{
|
||||
path: '/financial-reports/payable-aging-summary',
|
||||
component: lazy(() =>
|
||||
import('containers/FinancialStatements/APAgingSummary/APAgingSummary'),
|
||||
),
|
||||
breadcrumb: 'Payable Aging Summary',
|
||||
pageTitle: formatMessage({ id: 'payable_aging_summary' }),
|
||||
backLink: true,
|
||||
sidebarShrink: true,
|
||||
},
|
||||
{
|
||||
path: `/financial-reports/journal-sheet`,
|
||||
component: lazy(() =>
|
||||
|
||||
@@ -137,6 +137,41 @@ export const ARAgingSummaryTableRowsMapper = (sheet, total) => {
|
||||
];
|
||||
};
|
||||
|
||||
export const APAgingSummaryTableRowsMapper = (sheet, total) => {
|
||||
const rows = [];
|
||||
|
||||
const mapAging = (agingPeriods) => {
|
||||
return agingPeriods.reduce((acc, aging, index) => {
|
||||
acc[`aging-${index}`] = aging.total.formatted_amount;
|
||||
return acc;
|
||||
}, {});
|
||||
};
|
||||
sheet.vendors.forEach((vendor) => {
|
||||
const agingRow = mapAging(vendor.aging);
|
||||
|
||||
rows.push({
|
||||
rowType: 'vendor',
|
||||
name: vendor.vendor_name,
|
||||
...agingRow,
|
||||
current: vendor.current.formatted_amount,
|
||||
total: vendor.total.formatted_amount,
|
||||
});
|
||||
});
|
||||
if (rows.length <= 0) {
|
||||
return [];
|
||||
}
|
||||
return [
|
||||
...rows,
|
||||
{
|
||||
name: '',
|
||||
rowType: 'total',
|
||||
current: sheet.total.current.formatted_amount,
|
||||
...mapAging(sheet.total.aging),
|
||||
total: sheet.total.total.formatted_amount,
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
export const mapTrialBalanceSheetToRows = (sheet) => {
|
||||
const results = [];
|
||||
|
||||
|
||||
@@ -197,7 +197,7 @@ export default createReducer(initialState, {
|
||||
columns,
|
||||
vendors,
|
||||
total,
|
||||
// tableRows: APAgingSummaryTableRowsMapper({ vendors, columns, total }),
|
||||
tableRows: APAgingSummaryTableRowsMapper({ vendors, columns, total }),
|
||||
};
|
||||
state.payableAgingSummary.sheet = receivableSheet;
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user