mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-21 15:20:34 +00:00
Merge branch 'master' of https://github.com/abouolia/Ratteb
This commit is contained in:
@@ -4,65 +4,65 @@ import { omit } from 'lodash';
|
|||||||
import MultiSelect from 'components/MultiSelect';
|
import MultiSelect from 'components/MultiSelect';
|
||||||
import { FormattedMessage as T } from 'react-intl';
|
import { FormattedMessage as T } from 'react-intl';
|
||||||
|
|
||||||
export default function CustomersMultiSelect({
|
export default function ContactsMultiSelect({
|
||||||
customers,
|
contacts,
|
||||||
defaultText = <T id={'all_customers'} />,
|
defaultText = <T id={'all_customers'} />,
|
||||||
buttonProps,
|
buttonProps,
|
||||||
|
|
||||||
onCustomerSelected,
|
onCustomerSelected: onContactSelected,
|
||||||
...selectProps
|
...selectProps
|
||||||
}) {
|
}) {
|
||||||
const [selectedCustomers, setSelectedCustomers] = useState({});
|
const [selectedContacts, setSelectedContacts] = useState({});
|
||||||
|
|
||||||
const isCustomerSelect = useCallback(
|
const isContactSelect = useCallback(
|
||||||
(id) => typeof selectedCustomers[id] !== 'undefined',
|
(id) => typeof selectedContacts[id] !== 'undefined',
|
||||||
[selectedCustomers],
|
[selectedContacts],
|
||||||
);
|
);
|
||||||
|
|
||||||
const customerRenderer = useCallback(
|
const contactRenderer = useCallback(
|
||||||
(customer, { handleClick }) => (
|
(contact, { handleClick }) => (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
icon={isCustomerSelect(customer.id) ? 'tick' : 'blank'}
|
icon={isContactSelect(contact.id) ? 'tick' : 'blank'}
|
||||||
text={customer.display_name}
|
text={contact.display_name}
|
||||||
key={customer.id}
|
key={contact.id}
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
[isCustomerSelect],
|
[isContactSelect],
|
||||||
);
|
);
|
||||||
|
|
||||||
const countSelected = useMemo(() => Object.values(selectedCustomers).length, [
|
const countSelected = useMemo(() => Object.values(selectedContacts).length, [
|
||||||
selectedCustomers,
|
selectedContacts,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const onContactSelect = useCallback(
|
const onContactSelect = useCallback(
|
||||||
({ id }) => {
|
({ id }) => {
|
||||||
const selected = {
|
const selected = {
|
||||||
...(isCustomerSelect(id)
|
...(isContactSelect(id)
|
||||||
? {
|
? {
|
||||||
...omit(selectedCustomers, [id]),
|
...omit(selectedContacts, [id]),
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
...selectedCustomers,
|
...selectedContacts,
|
||||||
[id]: true,
|
[id]: true,
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
setSelectedCustomers({ ...selected });
|
setSelectedContacts({ ...selected });
|
||||||
onCustomerSelected && onCustomerSelected(selected);
|
onContactSelected && onContactSelected(selected);
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
setSelectedCustomers,
|
setSelectedContacts,
|
||||||
selectedCustomers,
|
selectedContacts,
|
||||||
isCustomerSelect,
|
isContactSelect,
|
||||||
onCustomerSelected,
|
onContactSelected,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MultiSelect
|
<MultiSelect
|
||||||
items={customers}
|
items={contacts}
|
||||||
noResults={<MenuItem disabled={true} text="No results." />}
|
noResults={<MenuItem disabled={true} text="No results." />}
|
||||||
itemRenderer={customerRenderer}
|
itemRenderer={contactRenderer}
|
||||||
popoverProps={{ minimal: true }}
|
popoverProps={{ minimal: true }}
|
||||||
filterable={true}
|
filterable={true}
|
||||||
onItemSelect={onContactSelect}
|
onItemSelect={onContactSelect}
|
||||||
@@ -43,7 +43,7 @@ import DashboardCard from './Dashboard/DashboardCard';
|
|||||||
import InputPrependText from './Forms/InputPrependText';
|
import InputPrependText from './Forms/InputPrependText';
|
||||||
import PageFormBigNumber from './PageFormBigNumber';
|
import PageFormBigNumber from './PageFormBigNumber';
|
||||||
import AccountsMultiSelect from './AccountsMultiSelect';
|
import AccountsMultiSelect from './AccountsMultiSelect';
|
||||||
import CustomersMultiSelect from './CustomersMultiSelect';
|
import ContactsMultiSelect from './ContactsMultiSelect';
|
||||||
import Skeleton from './Skeleton'
|
import Skeleton from './Skeleton'
|
||||||
import ContextMenu from './ContextMenu'
|
import ContextMenu from './ContextMenu'
|
||||||
import TableFastCell from './Datatable/TableFastCell';
|
import TableFastCell from './Datatable/TableFastCell';
|
||||||
@@ -99,7 +99,7 @@ export {
|
|||||||
PageFormBigNumber,
|
PageFormBigNumber,
|
||||||
AccountsMultiSelect,
|
AccountsMultiSelect,
|
||||||
DataTableEditable,
|
DataTableEditable,
|
||||||
CustomersMultiSelect,
|
ContactsMultiSelect,
|
||||||
TableFastCell,
|
TableFastCell,
|
||||||
Skeleton,
|
Skeleton,
|
||||||
ContextMenu,
|
ContextMenu,
|
||||||
|
|||||||
@@ -1,27 +1,20 @@
|
|||||||
import React, { useEffect, useState, useCallback } from 'react';
|
import React, { useState, useCallback, useEffect } from 'react';
|
||||||
import { useIntl } from 'react-intl';
|
|
||||||
import { queryCache, useQuery } from 'react-query';
|
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
|
||||||
|
import 'style/pages/FinancialStatements/ARAgingSummary.scss';
|
||||||
|
|
||||||
import { FinancialStatement } from 'components';
|
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 APAgingSummaryHeader from './APAgingSummaryHeader';
|
||||||
|
import APAgingSummaryActionsBar from './APAgingSummaryActionsBar';
|
||||||
import APAgingSummaryTable from './APAgingSummaryTable';
|
import APAgingSummaryTable from './APAgingSummaryTable';
|
||||||
|
import DashboardPageContent from 'components/Dashboard/DashboardPageContent';
|
||||||
|
import { APAgingSummaryProvider } from './APAgingSummaryProvider';
|
||||||
|
|
||||||
import withSettings from 'containers/Settings/withSettings';
|
import withSettings from 'containers/Settings/withSettings';
|
||||||
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
import withAPAgingSummaryActions from './withAPAgingSummaryActions'
|
||||||
import withAPAgingSummaryActions from './withAPAgingSummaryActions';
|
|
||||||
import withAPAgingSummary from './withAPAgingSummary';
|
|
||||||
import { transformFilterFormToQuery } from './common';
|
|
||||||
|
|
||||||
import { compose } from 'utils';
|
import { compose } from 'utils';
|
||||||
|
|
||||||
import 'style/pages/FinancialStatements/ARAgingSummary.scss';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AP aging summary report.
|
* AP aging summary report.
|
||||||
*/
|
*/
|
||||||
@@ -29,82 +22,47 @@ function APAgingSummary({
|
|||||||
// #withSettings
|
// #withSettings
|
||||||
organizationName,
|
organizationName,
|
||||||
|
|
||||||
// #withDashboardActions
|
|
||||||
changePageTitle,
|
|
||||||
setDashboardBackLink,
|
|
||||||
|
|
||||||
// #withAPAgingSummary
|
|
||||||
APAgingSummaryRefresh,
|
|
||||||
|
|
||||||
// #withAPAgingSummaryActions
|
// #withAPAgingSummaryActions
|
||||||
requestPayableAgingSummary,
|
toggleAPAgingSummaryFilterDrawer: toggleDisplayFilterDrawer,
|
||||||
refreshAPAgingSummary,
|
|
||||||
toggleFilterAPAgingSummary,
|
|
||||||
}) {
|
}) {
|
||||||
const { formatMessage } = useIntl();
|
const [filter, setFilter] = useState({
|
||||||
|
|
||||||
const [query, setQuery] = useState({
|
|
||||||
asDate: moment().endOf('day').format('YYYY-MM-DD'),
|
asDate: moment().endOf('day').format('YYYY-MM-DD'),
|
||||||
agingBeforeDays: 30,
|
agingBeforeDays: 30,
|
||||||
agingPeriods: 3,
|
agingPeriods: 3,
|
||||||
});
|
});
|
||||||
|
|
||||||
// handle fetching payable aging summary report.
|
// Handle filter submit.
|
||||||
const fetchAPAgingSummarySheet = useQuery(
|
const handleFilterSubmit = useCallback((filter) => {
|
||||||
['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) => {
|
|
||||||
const _filter = {
|
const _filter = {
|
||||||
...filter,
|
...filter,
|
||||||
asDate: moment(filter.asDate).format('YYYY-MM-DD'),
|
asDate: moment(filter.asDate).format('YYYY-MM-DD'),
|
||||||
};
|
};
|
||||||
setQuery(_filter);
|
setFilter(_filter);
|
||||||
refreshAPAgingSummary(true);
|
}, []);
|
||||||
toggleFilterAPAgingSummary(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
// Handle number format submit.
|
||||||
const handleNumberFormatSubmit = (numberFormat) => {
|
const handleNumberFormatSubmit = (numberFormat) => {
|
||||||
setQuery({
|
setFilter({
|
||||||
...query,
|
...filter,
|
||||||
numberFormat,
|
numberFormat,
|
||||||
});
|
});
|
||||||
refreshAPAgingSummary(true);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Hide the report filter drawer once the page unmount.
|
||||||
|
useEffect(() => () => {
|
||||||
|
toggleDisplayFilterDrawer(false);
|
||||||
|
}, [toggleDisplayFilterDrawer])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardInsider>
|
<APAgingSummaryProvider filter={filter}>
|
||||||
<APAgingSummaryActionsBar
|
<APAgingSummaryActionsBar
|
||||||
numberFormat={query.numberFormat}
|
numberFormat={filter.numberFormat}
|
||||||
onNumberFormatSubmit={handleNumberFormatSubmit}
|
onNumberFormatSubmit={handleNumberFormatSubmit}
|
||||||
/>
|
/>
|
||||||
<DashboardPageContent>
|
<DashboardPageContent>
|
||||||
<FinancialStatement>
|
<FinancialStatement>
|
||||||
<APAgingSummaryHeader
|
<APAgingSummaryHeader
|
||||||
pageFilter={query}
|
pageFilter={filter}
|
||||||
onSubmitFilter={handleFilterSubmit}
|
onSubmitFilter={handleFilterSubmit}
|
||||||
/>
|
/>
|
||||||
<div className={'financial-statement__body'}>
|
<div className={'financial-statement__body'}>
|
||||||
@@ -112,17 +70,13 @@ function APAgingSummary({
|
|||||||
</div>
|
</div>
|
||||||
</FinancialStatement>
|
</FinancialStatement>
|
||||||
</DashboardPageContent>
|
</DashboardPageContent>
|
||||||
</DashboardInsider>
|
</APAgingSummaryProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
withDashboardActions,
|
|
||||||
withAPAgingSummaryActions,
|
|
||||||
withSettings(({ organizationSettings }) => ({
|
withSettings(({ organizationSettings }) => ({
|
||||||
organizationName: organizationSettings.name,
|
organizationName: organizationSettings?.name,
|
||||||
})),
|
|
||||||
withAPAgingSummary(({ APAgingSummaryRefresh }) => ({
|
|
||||||
APAgingSummaryRefresh,
|
|
||||||
})),
|
})),
|
||||||
|
withAPAgingSummaryActions
|
||||||
)(APAgingSummary);
|
)(APAgingSummary);
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import {
|
|||||||
PopoverInteractionKind,
|
PopoverInteractionKind,
|
||||||
Position,
|
Position,
|
||||||
} from '@blueprintjs/core';
|
} from '@blueprintjs/core';
|
||||||
import { safeInvoke } from '@blueprintjs/core/lib/esm/common/utils';
|
|
||||||
|
|
||||||
import { FormattedMessage as T } from 'react-intl';
|
import { FormattedMessage as T } from 'react-intl';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
@@ -17,36 +16,42 @@ import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
|
|||||||
import { Icon } from 'components';
|
import { Icon } from 'components';
|
||||||
import NumberFormatDropdown from 'components/NumberFormatDropdown';
|
import NumberFormatDropdown from 'components/NumberFormatDropdown';
|
||||||
|
|
||||||
|
import { useAPAgingSummaryContext } from './APAgingSummaryProvider';
|
||||||
import withAPAgingSummary from './withAPAgingSummary';
|
import withAPAgingSummary from './withAPAgingSummary';
|
||||||
import withARAgingSummaryActions from './withAPAgingSummaryActions';
|
import withAPAgingSummaryActions from './withAPAgingSummaryActions';
|
||||||
|
|
||||||
import { compose } from 'utils';
|
import { saveInvoke, compose } from 'utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AP Aging summary sheet - Actions bar.
|
* AP Aging summary sheet - Actions bar.
|
||||||
*/
|
*/
|
||||||
function APAgingSummaryActionsBar({
|
function APAgingSummaryActionsBar({
|
||||||
//#withPayableAgingSummary
|
// #withPayableAgingSummary
|
||||||
payableAgingFilter,
|
payableAgingFilter,
|
||||||
payableAgingLoading,
|
|
||||||
|
|
||||||
//#withARAgingSummaryActions
|
// #withARAgingSummaryActions
|
||||||
toggleFilterAPAgingSummary,
|
toggleAPAgingSummaryFilterDrawer: toggleFilterDrawerDisplay,
|
||||||
refreshAPAgingSummary,
|
|
||||||
|
|
||||||
//#ownProps
|
//#ownProps
|
||||||
numberFormat,
|
numberFormat,
|
||||||
onNumberFormatSubmit,
|
onNumberFormatSubmit,
|
||||||
}) {
|
}) {
|
||||||
const handleFilterToggleClick = () => toggleFilterAPAgingSummary();
|
const { isAPAgingFetching, refetch } = useAPAgingSummaryContext();
|
||||||
|
|
||||||
|
const handleFilterToggleClick = () => {
|
||||||
|
toggleFilterDrawerDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
// handle recalculate report button.
|
// handle recalculate report button.
|
||||||
const handleRecalculateReport = () => refreshAPAgingSummary(true);
|
const handleRecalculateReport = () => {
|
||||||
|
refetch();
|
||||||
|
}
|
||||||
|
|
||||||
// handle number format submit.
|
// handle number format submit.
|
||||||
const handleNumberFormatSubmit = (numberFormat) =>
|
const handleNumberFormatSubmit = (numberFormat) => {
|
||||||
safeInvoke(onNumberFormatSubmit, numberFormat);
|
saveInvoke(onNumberFormatSubmit, numberFormat);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardActionsBar>
|
<DashboardActionsBar>
|
||||||
<NavbarGroup>
|
<NavbarGroup>
|
||||||
@@ -76,7 +81,7 @@ function APAgingSummaryActionsBar({
|
|||||||
<NumberFormatDropdown
|
<NumberFormatDropdown
|
||||||
numberFormat={numberFormat}
|
numberFormat={numberFormat}
|
||||||
onSubmit={handleNumberFormatSubmit}
|
onSubmit={handleNumberFormatSubmit}
|
||||||
submitDisabled={payableAgingLoading}
|
submitDisabled={isAPAgingFetching}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
minimal={true}
|
minimal={true}
|
||||||
@@ -113,11 +118,8 @@ function APAgingSummaryActionsBar({
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
withARAgingSummaryActions,
|
withAPAgingSummaryActions,
|
||||||
withAPAgingSummary(
|
withAPAgingSummary(({ APAgingSummaryFilterDrawer }) => ({
|
||||||
({ payableAgingSummaryLoading, payableAgingSummaryFilter }) => ({
|
isFilterDrawerOpen: APAgingSummaryFilterDrawer
|
||||||
payableAgingLoading: payableAgingSummaryLoading,
|
}))
|
||||||
payableAgingFilter: payableAgingSummaryFilter,
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
)(APAgingSummaryActionsBar);
|
)(APAgingSummaryActionsBar);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { FormattedMessage as T } from 'react-intl';
|
import { FormattedMessage as T } from 'react-intl';
|
||||||
import { Formik, Form, validateYupSchema } from 'formik';
|
import { Formik, Form } from 'formik';
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { Tabs, Tab, Button, Intent } from '@blueprintjs/core';
|
import { Tabs, Tab, Button, Intent } from '@blueprintjs/core';
|
||||||
@@ -17,12 +17,15 @@ import { compose } from 'utils';
|
|||||||
* AP Aging Summary Report - Drawer Header.
|
* AP Aging Summary Report - Drawer Header.
|
||||||
*/
|
*/
|
||||||
function APAgingSummaryHeader({
|
function APAgingSummaryHeader({
|
||||||
|
// #ownProps
|
||||||
pageFilter,
|
pageFilter,
|
||||||
onSubmitFilter,
|
onSubmitFilter,
|
||||||
payableAgingFilter,
|
|
||||||
|
|
||||||
// #withPayableAgingSummaryActions
|
// #withAPAgingSummaryActions
|
||||||
toggleFilterAPAgingSummary,
|
toggleAPAgingSummaryFilterDrawer: toggleFilterDrawerDisplay,
|
||||||
|
|
||||||
|
// #withAPAgingSummary
|
||||||
|
isFilterDrawerOpen
|
||||||
}) {
|
}) {
|
||||||
const validationSchema = Yup.object({
|
const validationSchema = Yup.object({
|
||||||
as_date: Yup.date().required().label('asDate'),
|
as_date: Yup.date().required().label('asDate'),
|
||||||
@@ -38,23 +41,32 @@ function APAgingSummaryHeader({
|
|||||||
.label('agingPeriods'),
|
.label('agingPeriods'),
|
||||||
});
|
});
|
||||||
|
|
||||||
// initial values.
|
// Initial values.
|
||||||
const initialValues = {
|
const initialValues = {
|
||||||
as_date: moment(pageFilter.asDate).toDate(),
|
as_date: moment(pageFilter.asDate).toDate(),
|
||||||
aging_days_before: 30,
|
aging_days_before: 30,
|
||||||
aging_periods: 3,
|
aging_periods: 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
// handle form submit.
|
// Handle form submit.
|
||||||
const handleSubmit = (values, { setSubmitting }) => {
|
const handleSubmit = (values, { setSubmitting }) => {
|
||||||
onSubmitFilter(values);
|
onSubmitFilter(values);
|
||||||
|
toggleFilterDrawerDisplay(false);
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
// handle cancel button click.
|
// handle cancel button click.
|
||||||
const handleCancelClick = () => toggleFilterAPAgingSummary();
|
const handleCancelClick = () => {
|
||||||
|
toggleFilterDrawerDisplay(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle the drawer closing.
|
||||||
|
const handleDrawerClose = () => {
|
||||||
|
toggleFilterDrawerDisplay(false);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FinancialStatementHeader isOpen={payableAgingFilter}>
|
<FinancialStatementHeader isOpen={isFilterDrawerOpen} drawerProps={{ onClose: handleDrawerClose }}>
|
||||||
<Formik
|
<Formik
|
||||||
initialValues={initialValues}
|
initialValues={initialValues}
|
||||||
validationSchema={validationSchema}
|
validationSchema={validationSchema}
|
||||||
@@ -84,7 +96,7 @@ function APAgingSummaryHeader({
|
|||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
withAPAgingSummaryActions,
|
withAPAgingSummaryActions,
|
||||||
withAPAgingSummary(({ payableAgingSummaryFilter }) => ({
|
withAPAgingSummary(({ APAgingSummaryFilterDrawer }) => ({
|
||||||
payableAgingFilter: payableAgingSummaryFilter,
|
isFilterDrawerOpen: APAgingSummaryFilterDrawer,
|
||||||
})),
|
})),
|
||||||
)(APAgingSummaryHeader);
|
)(APAgingSummaryHeader);
|
||||||
|
|||||||
@@ -1,9 +1,17 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { FastField } from 'formik';
|
import { FastField } from 'formik';
|
||||||
import { DateInput } from '@blueprintjs/datetime';
|
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 { 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 {
|
import {
|
||||||
momentFormatter,
|
momentFormatter,
|
||||||
tansformDateValue,
|
tansformDateValue,
|
||||||
@@ -15,6 +23,7 @@ import {
|
|||||||
* AP Aging Summary - Drawer Header - General Fields.
|
* AP Aging Summary - Drawer Header - General Fields.
|
||||||
*/
|
*/
|
||||||
export default function APAgingSummaryHeaderGeneral() {
|
export default function APAgingSummaryHeaderGeneral() {
|
||||||
|
const { vendors } = useAPAgingSummaryContext();
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Row>
|
<Row>
|
||||||
@@ -72,6 +81,19 @@ export default function APAgingSummaryHeaderGeneral() {
|
|||||||
</FastField>
|
</FastField>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</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>
|
</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 { FormattedMessage as T, useIntl } from 'react-intl';
|
||||||
import { DataTable } from 'components';
|
import { DataTable } from 'components';
|
||||||
import FinancialSheet from 'components/FinancialSheet';
|
import FinancialSheet from 'components/FinancialSheet';
|
||||||
|
|
||||||
import withAPAgingSummary from './withAPAgingSummary';
|
import { useAPAgingSummaryContext } from './APAgingSummaryProvider';
|
||||||
|
import { useAPAgingSummaryColumns } from './components';
|
||||||
import { compose, getColumnWidth } from 'utils';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AP aging summary table sheet.
|
* AP aging summary table sheet.
|
||||||
*/
|
*/
|
||||||
function APAgingSummaryTable({
|
export default function APAgingSummaryTable({
|
||||||
//#withPayableAgingSummary
|
|
||||||
payableAgingColumns,
|
|
||||||
payableAgingRows,
|
|
||||||
payableAgingLoading,
|
|
||||||
|
|
||||||
//#ownProps
|
//#ownProps
|
||||||
organizationName,
|
organizationName,
|
||||||
}) {
|
}) {
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
const agingColumns = useMemo(
|
|
||||||
() =>
|
|
||||||
payableAgingColumns.map((agingColumn) => {
|
|
||||||
return `${agingColumn.before_days} - ${
|
|
||||||
agingColumn.to_days || 'And Over'
|
|
||||||
}`;
|
|
||||||
}),
|
|
||||||
[payableAgingColumns],
|
|
||||||
);
|
|
||||||
|
|
||||||
const columns = useMemo(
|
// AP aging summary report content.
|
||||||
() => [
|
const {
|
||||||
{
|
APAgingSummary: { tableRows },
|
||||||
Header: <T id={'vendor_name'} />,
|
isAPAgingFetching,
|
||||||
accessor: 'name',
|
} = useAPAgingSummaryContext();
|
||||||
className: 'name',
|
|
||||||
width: 240,
|
// AP aging summary columns.
|
||||||
sticky: 'left',
|
const columns = useAPAgingSummaryColumns();
|
||||||
textOverview: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Header: <T id={'current'} />,
|
|
||||||
accessor: 'current',
|
|
||||||
className: 'current',
|
|
||||||
width: getColumnWidth(payableAgingRows, `current`, {
|
|
||||||
minWidth: 120,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
|
|
||||||
...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}`];
|
const rowClassNames = (row) => [`row-type--${row.original.rowType}`];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -74,12 +32,12 @@ function APAgingSummaryTable({
|
|||||||
name={'payable-aging-summary'}
|
name={'payable-aging-summary'}
|
||||||
sheetType={formatMessage({ id: 'payable_aging_summary' })}
|
sheetType={formatMessage({ id: 'payable_aging_summary' })}
|
||||||
asDate={new Date()}
|
asDate={new Date()}
|
||||||
loading={payableAgingLoading}
|
loading={isAPAgingFetching}
|
||||||
>
|
>
|
||||||
<DataTable
|
<DataTable
|
||||||
className={'bigcapital-datatable--financial-report'}
|
className={'bigcapital-datatable--financial-report'}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
data={payableAgingRows}
|
data={tableRows}
|
||||||
rowClassNames={rowClassNames}
|
rowClassNames={rowClassNames}
|
||||||
noInitialFetch={true}
|
noInitialFetch={true}
|
||||||
sticky={true}
|
sticky={true}
|
||||||
@@ -87,17 +45,3 @@ function APAgingSummaryTable({
|
|||||||
</FinancialSheet>
|
</FinancialSheet>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default compose(
|
|
||||||
withAPAgingSummary(
|
|
||||||
({
|
|
||||||
payableAgingSummaryLoading,
|
|
||||||
payableAgingSummaryColumns,
|
|
||||||
payableAgingSummaryRows,
|
|
||||||
}) => ({
|
|
||||||
payableAgingLoading: payableAgingSummaryLoading,
|
|
||||||
payableAgingColumns: payableAgingSummaryColumns,
|
|
||||||
payableAgingRows: payableAgingSummaryRows,
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
)(APAgingSummaryTable);
|
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
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],
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -1,33 +1,15 @@
|
|||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import {
|
import {
|
||||||
getFinancialSheetFactory,
|
APAgingSummaryFilterDrawerSelector,
|
||||||
getFinancialSheetColumnsFactory,
|
|
||||||
getFinancialSheetTableRowsFactory,
|
|
||||||
} from 'store/financialStatement/financialStatements.selectors';
|
} from 'store/financialStatement/financialStatements.selectors';
|
||||||
|
|
||||||
export default (mapState) => {
|
export default (mapState) => {
|
||||||
const mapStateToProps = (state, props) => {
|
const mapStateToProps = (state, props) => {
|
||||||
const getAPAgingSheet = getFinancialSheetFactory('payableAgingSummary');
|
|
||||||
const getAPAgingSheetColumns = getFinancialSheetColumnsFactory(
|
|
||||||
'payableAgingSummary',
|
|
||||||
);
|
|
||||||
const getAPAgingSheetRows = getFinancialSheetTableRowsFactory(
|
|
||||||
'payableAgingSummary',
|
|
||||||
);
|
|
||||||
|
|
||||||
const {
|
|
||||||
loading,
|
|
||||||
filter,
|
|
||||||
refresh,
|
|
||||||
} = state.financialStatements.payableAgingSummary;
|
|
||||||
|
|
||||||
const mapped = {
|
const mapped = {
|
||||||
payableAgingSummarySheet: getAPAgingSheet(state, props),
|
APAgingSummaryFilterDrawer: APAgingSummaryFilterDrawerSelector(
|
||||||
payableAgingSummaryColumns: getAPAgingSheetColumns(state, props),
|
state,
|
||||||
payableAgingSummaryRows: getAPAgingSheetRows(state, props),
|
props,
|
||||||
payableAgingSummaryLoading: loading,
|
),
|
||||||
payableAgingSummaryFilter: filter,
|
|
||||||
APAgingSummaryRefresh: refresh,
|
|
||||||
};
|
};
|
||||||
return mapState ? mapState(mapped, state, props) : mapped;
|
return mapState ? mapState(mapped, state, props) : mapped;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,18 +1,9 @@
|
|||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import {
|
import { toggleAPAgingSummaryFilterDrawer } from 'store/financialStatement/financialStatements.actions';
|
||||||
fetchPayableAginSummary,
|
|
||||||
payableAgingSummaryRefresh,
|
|
||||||
} from 'store/financialStatement/financialStatements.actions';
|
|
||||||
|
|
||||||
const mapActionsToProps = (dispatch) => ({
|
const mapActionsToProps = (dispatch) => ({
|
||||||
requestPayableAgingSummary: (query) =>
|
toggleAPAgingSummaryFilterDrawer: (toggle) =>
|
||||||
dispatch(fetchPayableAginSummary({ query })),
|
dispatch(toggleAPAgingSummaryFilterDrawer(toggle)),
|
||||||
refreshAPAgingSummary: (refresh) =>
|
|
||||||
dispatch(payableAgingSummaryRefresh(refresh)),
|
|
||||||
toggleFilterAPAgingSummary: () =>
|
|
||||||
dispatch({
|
|
||||||
type: 'PAYABLE_AGING_SUMMARY_FILTER_TOGGLE',
|
|
||||||
}),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(null, mapActionsToProps);
|
export default connect(null, mapActionsToProps);
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ function ARAgingSummaryActionsBar({
|
|||||||
const { isARAgingFetching, refetch } = useARAgingSummaryContext();
|
const { isARAgingFetching, refetch } = useARAgingSummaryContext();
|
||||||
|
|
||||||
const handleFilterToggleClick = () => {
|
const handleFilterToggleClick = () => {
|
||||||
toggleDisplayFilterDrawer(false);
|
toggleDisplayFilterDrawer();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handles re-calculate report button.
|
// Handles re-calculate report button.
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ function ARAgingSummaryHeader({
|
|||||||
toggleARAgingSummaryFilterDrawer: toggleFilterDrawerDisplay,
|
toggleARAgingSummaryFilterDrawer: toggleFilterDrawerDisplay,
|
||||||
|
|
||||||
// #withARAgingSummary
|
// #withARAgingSummary
|
||||||
isFilterDrawerOpen
|
isFilterDrawerOpen,
|
||||||
}) {
|
}) {
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
asDate: Yup.date().required().label('asDate'),
|
asDate: Yup.date().required().label('asDate'),
|
||||||
@@ -53,13 +53,22 @@ function ARAgingSummaryHeader({
|
|||||||
toggleFilterDrawerDisplay(false);
|
toggleFilterDrawerDisplay(false);
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle cancel button click.
|
// Handle cancel button click.
|
||||||
const handleCancelClick = () => {
|
const handleCancelClick = () => {
|
||||||
toggleFilterDrawerDisplay(false);
|
toggleFilterDrawerDisplay(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Handle the drawer close.
|
||||||
|
const handleDrawerClose = () => {
|
||||||
|
toggleFilterDrawerDisplay(false);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FinancialStatementHeader isOpen={isFilterDrawerOpen}>
|
<FinancialStatementHeader
|
||||||
|
isOpen={isFilterDrawerOpen}
|
||||||
|
drawerProps={{ onClose: handleDrawerClose }}
|
||||||
|
>
|
||||||
<Formik
|
<Formik
|
||||||
initialValues={initialValues}
|
initialValues={initialValues}
|
||||||
validationSchema={validationSchema}
|
validationSchema={validationSchema}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import {
|
|||||||
} from '@blueprintjs/core';
|
} from '@blueprintjs/core';
|
||||||
import { FormattedMessage as T } from 'react-intl';
|
import { FormattedMessage as T } from 'react-intl';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { CustomersMultiSelect, Row, Col, FieldHint } from 'components';
|
import { ContactsMultiSelect, Row, Col, FieldHint } from 'components';
|
||||||
import { momentFormatter } from 'utils';
|
import { momentFormatter } from 'utils';
|
||||||
|
|
||||||
import { useARAgingSummaryContext } from './ARAgingSummaryProvider';
|
import { useARAgingSummaryContext } from './ARAgingSummaryProvider';
|
||||||
@@ -97,7 +97,7 @@ export default function ARAgingSummaryHeaderGeneral() {
|
|||||||
label={<T id={'specific_customers'} />}
|
label={<T id={'specific_customers'} />}
|
||||||
className={classNames('form-group--select-list', Classes.FILL)}
|
className={classNames('form-group--select-list', Classes.FILL)}
|
||||||
>
|
>
|
||||||
<CustomersMultiSelect customers={customers} />
|
<ContactsMultiSelect contacts={customers} />
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</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,
|
profitLossSheetReducer,
|
||||||
generalLedgerTableRowsReducer,
|
generalLedgerTableRowsReducer,
|
||||||
journalTableRowsReducer,
|
journalTableRowsReducer,
|
||||||
ARAgingSummaryTableRowsMapper
|
ARAgingSummaryTableRowsMapper,
|
||||||
|
APAgingSummaryTableRowsMapper
|
||||||
} from 'containers/FinancialStatements/reducers';
|
} from 'containers/FinancialStatements/reducers';
|
||||||
import useApiRequest from '../useRequest';
|
import useApiRequest from '../useRequest';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve balance sheet.
|
* Retrieve balance sheet.
|
||||||
*/
|
*/
|
||||||
@@ -27,7 +28,7 @@ export function useBalanceSheet(query, props) {
|
|||||||
tableRows: balanceSheetRowsReducer(res.data.data),
|
tableRows: balanceSheetRowsReducer(res.data.data),
|
||||||
...res.data,
|
...res.data,
|
||||||
}),
|
}),
|
||||||
...props
|
...props,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -69,8 +70,8 @@ export function useTrialBalanceSheet(query, props) {
|
|||||||
tableRows: [],
|
tableRows: [],
|
||||||
data: [],
|
data: [],
|
||||||
query: {},
|
query: {},
|
||||||
})
|
}),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -101,7 +102,7 @@ export function useProfitLossSheet(query, props) {
|
|||||||
columns: [],
|
columns: [],
|
||||||
query: {},
|
query: {},
|
||||||
}),
|
}),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -132,7 +133,7 @@ export function useGeneralLedgerSheet(query, props) {
|
|||||||
data: {},
|
data: {},
|
||||||
query: {},
|
query: {},
|
||||||
}),
|
}),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -143,12 +144,11 @@ export function useJournalSheet(query, props) {
|
|||||||
|
|
||||||
const states = useQuery(
|
const states = useQuery(
|
||||||
['FINANCIAL-REPORT', 'JOURNAL', query],
|
['FINANCIAL-REPORT', 'JOURNAL', query],
|
||||||
() =>
|
() => apiRequest.get('/financial_statements/journal', { params: query }),
|
||||||
apiRequest.get('/financial_statements/journal', { params: query }),
|
|
||||||
{
|
{
|
||||||
select: (res) => ({
|
select: (res) => ({
|
||||||
tableRows: journalTableRowsReducer(res.data.data),
|
tableRows: journalTableRowsReducer(res.data.data),
|
||||||
...res.data,
|
...res.data,
|
||||||
}),
|
}),
|
||||||
...props,
|
...props,
|
||||||
},
|
},
|
||||||
@@ -160,8 +160,8 @@ export function useJournalSheet(query, props) {
|
|||||||
data: {},
|
data: {},
|
||||||
tableRows: [],
|
tableRows: [],
|
||||||
query: {},
|
query: {},
|
||||||
})
|
}),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -185,7 +185,7 @@ export function useARAgingSummaryReport(query, props) {
|
|||||||
customers: res.data.data.customers,
|
customers: res.data.data.customers,
|
||||||
total: res.data.data.total,
|
total: res.data.data.total,
|
||||||
columns: res.data.columns,
|
columns: res.data.columns,
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
initialData: {
|
initialData: {
|
||||||
data: {
|
data: {
|
||||||
@@ -194,11 +194,50 @@ export function useARAgingSummaryReport(query, props) {
|
|||||||
total: {},
|
total: {},
|
||||||
},
|
},
|
||||||
columns: [],
|
columns: [],
|
||||||
tableRows: []
|
tableRows: [],
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
initialDataUpdatedAt: 0,
|
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',
|
adjustment_reasons: 'Adjustment reasons',
|
||||||
specific_customers: 'Specific Customers',
|
specific_customers: 'Specific Customers',
|
||||||
all_customers: 'All Customers',
|
all_customers: 'All Customers',
|
||||||
|
all_vendors: 'All Vendors',
|
||||||
selected_customers: '{count} Selected Customers',
|
selected_customers: '{count} Selected Customers',
|
||||||
transaction_number: 'Transaction #',
|
transaction_number: 'Transaction #',
|
||||||
running_balance: 'Running balance',
|
running_balance: 'Running balance',
|
||||||
@@ -976,4 +977,6 @@ export default {
|
|||||||
receipt_paper: 'Receipt Paper',
|
receipt_paper: 'Receipt Paper',
|
||||||
payable_aging_summary: 'Payable Aging Summary',
|
payable_aging_summary: 'Payable Aging Summary',
|
||||||
payment_receive_paper: 'Payment Receive Paper',
|
payment_receive_paper: 'Payment Receive Paper',
|
||||||
|
specific_vendors: 'Specific Vendors',
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -159,13 +159,16 @@ export default [
|
|||||||
backLink: true,
|
backLink: true,
|
||||||
sidebarShrink: true,
|
sidebarShrink: true,
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// path: '/financial-reports/payable-aging-summary',
|
path: '/financial-reports/payable-aging-summary',
|
||||||
// component: lazy(() =>
|
component: lazy(() =>
|
||||||
// import('containers/FinancialStatements/APAgingSummary/APAgingSummary'),
|
import('containers/FinancialStatements/APAgingSummary/APAgingSummary'),
|
||||||
// ),
|
),
|
||||||
// breadcrumb: 'Payable Aging Summary',
|
breadcrumb: 'Payable Aging Summary',
|
||||||
// },
|
pageTitle: formatMessage({ id: 'payable_aging_summary' }),
|
||||||
|
backLink: true,
|
||||||
|
sidebarShrink: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: `/financial-reports/journal-sheet`,
|
path: `/financial-reports/journal-sheet`,
|
||||||
component: lazy(() =>
|
component: lazy(() =>
|
||||||
|
|||||||
@@ -76,4 +76,17 @@ export function toggleARAgingSummaryFilterDrawer(toggle) {
|
|||||||
toggle,
|
toggle,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggles display of the AP aging summary filter drawer.
|
||||||
|
* @param {boolean} toggle -
|
||||||
|
*/
|
||||||
|
export function toggleAPAgingSummaryFilterDrawer(toggle) {
|
||||||
|
return {
|
||||||
|
type: `${t.AP_AGING_SUMMARY}/${t.DISPLAY_FILTER_DRAWER_TOGGLE}`,
|
||||||
|
payload: {
|
||||||
|
toggle,
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
@@ -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) => {
|
export const mapTrialBalanceSheetToRows = (sheet) => {
|
||||||
const results = [];
|
const results = [];
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,11 @@ export const ARAgingSummaryFilterDrawerSelector = (state) => {
|
|||||||
return filterDrawerByTypeSelector('ARAgingSummary')(state);
|
return filterDrawerByTypeSelector('ARAgingSummary')(state);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const APAgingSummaryFilterDrawerSelector = (state) => {
|
||||||
|
return filterDrawerByTypeSelector('APAgingSummary')(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve balance sheet filter drawer.
|
* Retrieve balance sheet filter drawer.
|
||||||
*/
|
*/
|
||||||
@@ -94,6 +99,17 @@ export const getARAgingSummaryFilterDrawer = createSelector(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve whether display AR aging summary drawer filter.
|
||||||
|
*/
|
||||||
|
export const getAPAgingSummaryFilterDrawer = createSelector(
|
||||||
|
APAgingSummaryFilterDrawerSelector,
|
||||||
|
(isOpen) => {
|
||||||
|
return isOpen;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve financial statement query by the given sheet index.
|
* Retrieve financial statement query by the given sheet index.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user