diff --git a/client/src/components/CustomersMultiSelect.js b/client/src/components/ContactsMultiSelect.js similarity index 52% rename from client/src/components/CustomersMultiSelect.js rename to client/src/components/ContactsMultiSelect.js index 1afa5a2f2..3d622af9f 100644 --- a/client/src/components/CustomersMultiSelect.js +++ b/client/src/components/ContactsMultiSelect.js @@ -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 = , 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 }) => ( ), - [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 ( } - itemRenderer={customerRenderer} + itemRenderer={contactRenderer} popoverProps={{ minimal: true }} filterable={true} onItemSelect={onContactSelect} diff --git a/client/src/components/index.js b/client/src/components/index.js index 18ade28b4..19befa37f 100644 --- a/client/src/components/index.js +++ b/client/src/components/index.js @@ -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, diff --git a/client/src/containers/FinancialStatements/APAgingSummary/APAgingSummary.js b/client/src/containers/FinancialStatements/APAgingSummary/APAgingSummary.js index 79b6e7025..22df8f881 100644 --- a/client/src/containers/FinancialStatements/APAgingSummary/APAgingSummary.js +++ b/client/src/containers/FinancialStatements/APAgingSummary/APAgingSummary.js @@ -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 ( - + @@ -112,17 +62,12 @@ function APAgingSummary({ - + ); } export default compose( - withDashboardActions, - withAPAgingSummaryActions, withSettings(({ organizationSettings }) => ({ - organizationName: organizationSettings.name, - })), - withAPAgingSummary(({ APAgingSummaryRefresh }) => ({ - APAgingSummaryRefresh, + organizationName: organizationSettings?.name, })), )(APAgingSummary); diff --git a/client/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryActionsBar.js b/client/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryActionsBar.js index 5426ab7af..1429e7c5b 100644 --- a/client/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryActionsBar.js +++ b/client/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryActionsBar.js @@ -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 ( @@ -76,7 +76,7 @@ function APAgingSummaryActionsBar({ } 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); diff --git a/client/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryHeader.js b/client/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryHeader.js index 91dea8281..e191b98f9 100644 --- a/client/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryHeader.js +++ b/client/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryHeader.js @@ -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 ( @@ -72,6 +81,19 @@ export default function APAgingSummaryHeaderGeneral() { + + + } + className={classNames('form-group--select-list', Classes.FILL)} + > + } + contacts={vendors} + /> + + + ); } diff --git a/client/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryProvider.js b/client/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryProvider.js new file mode 100644 index 000000000..0a5629729 --- /dev/null +++ b/client/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryProvider.js @@ -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 ( + + + + ); +} + + +const useAPAgingSummaryContext = () => useContext(APAgingSummaryContext); + + +export { APAgingSummaryProvider, useAPAgingSummaryContext }; diff --git a/client/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryTable.js b/client/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryTable.js index 303d7c28b..bd433e254 100644 --- a/client/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryTable.js +++ b/client/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryTable.js @@ -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: , - accessor: 'name', - className: 'name', - width: 240, - sticky: 'left', - textOverview: true, - }, - { - Header: , - 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: , - 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} > ); } - -export default compose( - withAPAgingSummary( - ({ - payableAgingSummaryLoading, - payableAgingSummaryColumns, - payableAgingSummaryRows, - }) => ({ - payableAgingLoading: payableAgingSummaryLoading, - payableAgingColumns: payableAgingSummaryColumns, - payableAgingRows: payableAgingSummaryRows, - }), - ), -)(APAgingSummaryTable); diff --git a/client/src/containers/FinancialStatements/APAgingSummary/components.js b/client/src/containers/FinancialStatements/APAgingSummary/components.js new file mode 100644 index 000000000..b97cb9022 --- /dev/null +++ b/client/src/containers/FinancialStatements/APAgingSummary/components.js @@ -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: , + accessor: 'name', + className: 'name', + width: 240, + sticky: 'left', + textOverview: true, + }, + { + Header: , + 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: , + accessor: 'total', + width: getColumnWidth(tableRows, 'total', { + minWidth: 120, + }), + }, + ], + [tableRows, agingColumns], + ); +}; diff --git a/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryHeaderGeneral.js b/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryHeaderGeneral.js index 4636882bf..5bb68fc9f 100644 --- a/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryHeaderGeneral.js +++ b/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryHeaderGeneral.js @@ -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={} className={classNames('form-group--select-list', Classes.FILL)} > - + diff --git a/client/src/containers/FinancialStatements/reducers.js b/client/src/containers/FinancialStatements/reducers.js index 775a2c074..6af950eea 100644 --- a/client/src/containers/FinancialStatements/reducers.js +++ b/client/src/containers/FinancialStatements/reducers.js @@ -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, + }, + ]; +}; diff --git a/client/src/hooks/query/financialReports.js b/client/src/hooks/query/financialReports.js index b7bdf7d51..b7b03fdaa 100644 --- a/client/src/hooks/query/financialReports.js +++ b/client/src/hooks/query/financialReports.js @@ -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, }, ); } diff --git a/client/src/lang/en/index.js b/client/src/lang/en/index.js index 5b9e390d8..4e436e30d 100644 --- a/client/src/lang/en/index.js +++ b/client/src/lang/en/index.js @@ -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', + }; diff --git a/client/src/routes/dashboard.js b/client/src/routes/dashboard.js index cb5583475..3a1108507 100644 --- a/client/src/routes/dashboard.js +++ b/client/src/routes/dashboard.js @@ -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(() => diff --git a/client/src/store/financialStatement/financialStatements.mappers.js b/client/src/store/financialStatement/financialStatements.mappers.js index e771198cf..7377bbb23 100644 --- a/client/src/store/financialStatement/financialStatements.mappers.js +++ b/client/src/store/financialStatement/financialStatements.mappers.js @@ -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 = []; diff --git a/client/src/store/financialStatement/financialStatements.reducer.js b/client/src/store/financialStatement/financialStatements.reducer.js index bd6844af9..705de53e1 100644 --- a/client/src/store/financialStatement/financialStatements.reducer.js +++ b/client/src/store/financialStatement/financialStatements.reducer.js @@ -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; },