mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-20 23:00:34 +00:00
feat(webapp): wip sales tax liability summary report
This commit is contained in:
@@ -169,6 +169,7 @@ export const ReportsAction = {
|
|||||||
READ_INVENTORY_VALUATION_SUMMARY: 'read-inventory-valuation-summary',
|
READ_INVENTORY_VALUATION_SUMMARY: 'read-inventory-valuation-summary',
|
||||||
READ_INVENTORY_ITEM_DETAILS: 'read-inventory-item-details',
|
READ_INVENTORY_ITEM_DETAILS: 'read-inventory-item-details',
|
||||||
READ_CASHFLOW_ACCOUNT_TRANSACTION: 'read-cashflow-account-transactions',
|
READ_CASHFLOW_ACCOUNT_TRANSACTION: 'read-cashflow-account-transactions',
|
||||||
|
READ_SALES_TAX_LIABILITY_SUMMARY: 'read-sales-tax-liability-summary',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PreferencesAbility = {
|
export const PreferencesAbility = {
|
||||||
|
|||||||
@@ -85,6 +85,13 @@ export const financialReportMenus = [
|
|||||||
subject: AbilitySubject.Report,
|
subject: AbilitySubject.Report,
|
||||||
ability: ReportsAction.READ_PROFIT_LOSS,
|
ability: ReportsAction.READ_PROFIT_LOSS,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: 'Sales Tax Liability Summary',
|
||||||
|
desc: 'Reports the total amount of sales tax collected from customers',
|
||||||
|
link: '/financial-reports/sales-tax-liability-summary',
|
||||||
|
subject: AbilitySubject.Report,
|
||||||
|
ability: ReportsAction.READ_SALES_TAX_LIABILITY_SUMMARY,
|
||||||
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import React, { useEffect } from 'react';
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
|
import { SalesTaxLiabilitySummaryLoadingBar } from './components';
|
||||||
|
import { FinancialStatement, DashboardPageContent } from '@/components';
|
||||||
|
|
||||||
|
import SalesTaxLiabilitySummaryHeader from './SalesTaxLiabilitySummaryHeader';
|
||||||
|
import SalesTaxLiabilitySummaryActionsBar from './SalesTaxLiabilitySummaryActionsBar';
|
||||||
|
import { SalesTaxLiabilitySummaryBoot } from './SalesTaxLiabilitySummaryBoot';
|
||||||
|
import { SalesTaxLiabilitySummaryBody } from './SalesTaxLiabilitySummaryBody';
|
||||||
|
import { useSalesTaxLiabilitySummaryQuery } from './utils';
|
||||||
|
import withSalesTaxLiabilitySummaryActions from './withSalesTaxLiabilitySummaryActions';
|
||||||
|
import { compose } from '@/utils';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sales tax liability summary.
|
||||||
|
* @returns {React.JSX}
|
||||||
|
*/
|
||||||
|
function SalesTaxLiabilitySummary({
|
||||||
|
// #withSalesTaxLiabilitySummaryActions
|
||||||
|
toggleSalesTaxLiabilitySummaryFilterDrawer,
|
||||||
|
}) {
|
||||||
|
const [query, setQuery] = useSalesTaxLiabilitySummaryQuery();
|
||||||
|
|
||||||
|
const handleFilterSubmit = (filter) => {
|
||||||
|
const newFilter = {
|
||||||
|
...filter,
|
||||||
|
fromDate: moment(filter.fromDate).format('YYYY-MM-DD'),
|
||||||
|
toDate: moment(filter.toDate).format('YYYY-MM-DD'),
|
||||||
|
};
|
||||||
|
setQuery({ ...newFilter });
|
||||||
|
};
|
||||||
|
// Handle number format submit.
|
||||||
|
const handleNumberFormatSubmit = (values) => {
|
||||||
|
setQuery({
|
||||||
|
...query,
|
||||||
|
numberFormat: values,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// Hides the filter drawer once the page unmount.
|
||||||
|
useEffect(
|
||||||
|
() => () => {
|
||||||
|
toggleSalesTaxLiabilitySummaryFilterDrawer(false);
|
||||||
|
},
|
||||||
|
[toggleSalesTaxLiabilitySummaryFilterDrawer],
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SalesTaxLiabilitySummaryBoot filter={query}>
|
||||||
|
<SalesTaxLiabilitySummaryActionsBar
|
||||||
|
numberFormat={query.numberFormat}
|
||||||
|
onNumberFormatSubmit={handleNumberFormatSubmit}
|
||||||
|
/>
|
||||||
|
<SalesTaxLiabilitySummaryLoadingBar />
|
||||||
|
|
||||||
|
<DashboardPageContent>
|
||||||
|
<FinancialStatement>
|
||||||
|
<SalesTaxLiabilitySummaryHeader
|
||||||
|
pageFilter={query}
|
||||||
|
onSubmitFilter={handleFilterSubmit}
|
||||||
|
/>
|
||||||
|
<SalesTaxLiabilitySummaryBody />
|
||||||
|
</FinancialStatement>
|
||||||
|
</DashboardPageContent>
|
||||||
|
</SalesTaxLiabilitySummaryBoot>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default compose(withSalesTaxLiabilitySummaryActions)(
|
||||||
|
SalesTaxLiabilitySummary,
|
||||||
|
);
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
NavbarGroup,
|
||||||
|
Button,
|
||||||
|
Classes,
|
||||||
|
NavbarDivider,
|
||||||
|
Popover,
|
||||||
|
PopoverInteractionKind,
|
||||||
|
Position,
|
||||||
|
} from '@blueprintjs/core';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import { DashboardActionsBar, FormattedMessage as T, Icon } from '@/components';
|
||||||
|
|
||||||
|
import NumberFormatDropdown from '@/components/NumberFormatDropdown';
|
||||||
|
|
||||||
|
import { compose, saveInvoke } from '@/utils';
|
||||||
|
import { useSalesTaxLiabilitySummaryContext } from './SalesTaxLiabilitySummaryBoot';
|
||||||
|
import withSalesTaxLiabilitySummary from './withSalesTaxLiabilitySummary';
|
||||||
|
import withSalesTaxLiabilitySummaryActions from './withSalesTaxLiabilitySummaryActions';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sales tax liability summary - actions bar.
|
||||||
|
*/
|
||||||
|
function SalesTaxLiabilitySummaryActionsBar({
|
||||||
|
// #withSalesTaxLiabilitySummary
|
||||||
|
salesTaxLiabilitySummaryFilter,
|
||||||
|
|
||||||
|
// #withSalesTaxLiabilitySummaryActions
|
||||||
|
toggleBalanceSheetFilterDrawer: toggleFilterDrawer,
|
||||||
|
|
||||||
|
// #ownProps
|
||||||
|
numberFormat,
|
||||||
|
onNumberFormatSubmit,
|
||||||
|
}) {
|
||||||
|
const { isLoading, refetchBalanceSheet } =
|
||||||
|
useSalesTaxLiabilitySummaryContext();
|
||||||
|
|
||||||
|
// Handle filter toggle click.
|
||||||
|
const handleFilterToggleClick = () => {
|
||||||
|
toggleFilterDrawer();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle recalculate the report button.
|
||||||
|
const handleRecalcReport = () => {
|
||||||
|
refetchBalanceSheet();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle number format form submit.
|
||||||
|
const handleNumberFormatSubmit = (values) => {
|
||||||
|
saveInvoke(onNumberFormatSubmit, values);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DashboardActionsBar>
|
||||||
|
<NavbarGroup>
|
||||||
|
<Button
|
||||||
|
className={classNames(Classes.MINIMAL, 'button--gray-highlight')}
|
||||||
|
text={<T id={'recalc_report'} />}
|
||||||
|
onClick={handleRecalcReport}
|
||||||
|
icon={<Icon icon="refresh-16" iconSize={16} />}
|
||||||
|
/>
|
||||||
|
<NavbarDivider />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
className={classNames(Classes.MINIMAL, 'button--table-views')}
|
||||||
|
icon={<Icon icon="cog-16" iconSize={16} />}
|
||||||
|
text={
|
||||||
|
!salesTaxLiabilitySummaryFilter ? (
|
||||||
|
<T id={'customize_report'} />
|
||||||
|
) : (
|
||||||
|
<T id={'hide_customizer'} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onClick={handleFilterToggleClick}
|
||||||
|
active={salesTaxLiabilitySummaryFilter}
|
||||||
|
/>
|
||||||
|
<NavbarDivider />
|
||||||
|
|
||||||
|
<Popover
|
||||||
|
content={
|
||||||
|
<NumberFormatDropdown
|
||||||
|
numberFormat={numberFormat}
|
||||||
|
onSubmit={handleNumberFormatSubmit}
|
||||||
|
submitDisabled={isLoading}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
minimal={true}
|
||||||
|
interactionKind={PopoverInteractionKind.CLICK}
|
||||||
|
position={Position.BOTTOM_LEFT}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
className={classNames(Classes.MINIMAL, 'button--filter')}
|
||||||
|
text={<T id={'format'} />}
|
||||||
|
icon={<Icon icon="numbers" width={23} height={16} />}
|
||||||
|
/>
|
||||||
|
</Popover>
|
||||||
|
|
||||||
|
<Popover
|
||||||
|
// content={}
|
||||||
|
interactionKind={PopoverInteractionKind.CLICK}
|
||||||
|
position={Position.BOTTOM_LEFT}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
className={classNames(Classes.MINIMAL, 'button--filter')}
|
||||||
|
text={<T id={'filter'} />}
|
||||||
|
icon={<Icon icon="filter-16" iconSize={16} />}
|
||||||
|
/>
|
||||||
|
</Popover>
|
||||||
|
|
||||||
|
<NavbarDivider />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
className={Classes.MINIMAL}
|
||||||
|
icon={<Icon icon="print-16" iconSize={16} />}
|
||||||
|
text={<T id={'print'} />}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
className={Classes.MINIMAL}
|
||||||
|
icon={<Icon icon="file-export-16" iconSize={16} />}
|
||||||
|
text={<T id={'export'} />}
|
||||||
|
/>
|
||||||
|
</NavbarGroup>
|
||||||
|
</DashboardActionsBar>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default compose(
|
||||||
|
withSalesTaxLiabilitySummary(({ salesTaxLiabilitySummaryFilter }) => ({
|
||||||
|
salesTaxLiabilitySummaryFilter,
|
||||||
|
})),
|
||||||
|
withSalesTaxLiabilitySummaryActions,
|
||||||
|
)(SalesTaxLiabilitySummaryActionsBar);
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { FinancialReportBody } from '../FinancialReportPage';
|
||||||
|
import { FinancialSheetSkeleton } from '@/components';
|
||||||
|
import { SalesTaxLiabilitySummaryTable } from './SalesTaxLiabilitySummaryTable';
|
||||||
|
|
||||||
|
import withCurrentOrganization from '@/containers/Organization/withCurrentOrganization';
|
||||||
|
import { useSalesTaxLiabilitySummaryContext } from './SalesTaxLiabilitySummaryBoot';
|
||||||
|
import { compose } from '@/utils';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sales tax liability summary body.
|
||||||
|
* @returns {React.JSX}
|
||||||
|
*/
|
||||||
|
function SalesTaxLiabilitySummaryBodyRoot({
|
||||||
|
// #withCurrentOrganization
|
||||||
|
organizationName,
|
||||||
|
}) {
|
||||||
|
const { isLoading } = useSalesTaxLiabilitySummaryContext();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FinancialReportBody>
|
||||||
|
{isLoading ? (
|
||||||
|
<FinancialSheetSkeleton />
|
||||||
|
) : (
|
||||||
|
<SalesTaxLiabilitySummaryTable />
|
||||||
|
)}
|
||||||
|
</FinancialReportBody>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SalesTaxLiabilitySummaryBody = compose(
|
||||||
|
withCurrentOrganization(({ organization }) => ({
|
||||||
|
organizationName: organization.name,
|
||||||
|
})),
|
||||||
|
)(SalesTaxLiabilitySummaryBodyRoot);
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import React, { createContext, useContext } from 'react';
|
||||||
|
import FinancialReportPage from '../FinancialReportPage';
|
||||||
|
import { transformFilterFormToQuery } from '../common';
|
||||||
|
import { useSalesTaxLiabilitySummary } from '@/hooks/query';
|
||||||
|
|
||||||
|
const SalesTaxLiabilitySummaryContext = createContext();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sales tax liability summary boot.
|
||||||
|
* @returns {JSX.Element}
|
||||||
|
*/
|
||||||
|
function SalesTaxLiabilitySummaryBoot({ filter, ...props }) {
|
||||||
|
// Transformes the given filter to query.
|
||||||
|
const query = React.useMemo(
|
||||||
|
() => transformFilterFormToQuery(filter),
|
||||||
|
[filter],
|
||||||
|
);
|
||||||
|
// Fetches the sales tax liability summary report.
|
||||||
|
const {
|
||||||
|
data: salesTaxLiabilitySummary,
|
||||||
|
isFetching,
|
||||||
|
isLoading,
|
||||||
|
refetch,
|
||||||
|
} = useSalesTaxLiabilitySummary(query, { keepPreviousData: true });
|
||||||
|
|
||||||
|
const provider = {
|
||||||
|
salesTaxLiabilitySummary,
|
||||||
|
isFetching,
|
||||||
|
isLoading,
|
||||||
|
query,
|
||||||
|
filter,
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FinancialReportPage name={'sales-tax-liability-summary'}>
|
||||||
|
<SalesTaxLiabilitySummaryContext.Provider value={provider} {...props} />
|
||||||
|
</FinancialReportPage>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const useSalesTaxLiabilitySummaryContext = () =>
|
||||||
|
useContext(SalesTaxLiabilitySummaryContext);
|
||||||
|
|
||||||
|
export { SalesTaxLiabilitySummaryBoot, useSalesTaxLiabilitySummaryContext };
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import React from 'react';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
import moment from 'moment';
|
||||||
|
import { Tabs, Tab, Button, Intent } from '@blueprintjs/core';
|
||||||
|
import { Formik, Form } from 'formik';
|
||||||
|
|
||||||
|
import { FormattedMessage as T } from '@/components';
|
||||||
|
import { useFeatureCan } from '@/hooks/state';
|
||||||
|
import { Features } from '@/constants';
|
||||||
|
|
||||||
|
import BalanceSheetHeaderGeneralPanal from './BalanceSheetHeaderGeneralPanal';
|
||||||
|
import FinancialStatementHeader from '../../FinancialStatements/FinancialStatementHeader';
|
||||||
|
|
||||||
|
import { compose, transformToForm } from '@/utils';
|
||||||
|
import {
|
||||||
|
getDefaultSalesTaxLiablitySummaryQuery,
|
||||||
|
getSalesTaxLiabilitySummaryQueryValidation,
|
||||||
|
} from './utils';
|
||||||
|
import withSalesTaxLiabilitySummary from './withSalesTaxLiabilitySummary';
|
||||||
|
import withSalesTaxLiabilitySummaryActions from './withSalesTaxLiabilitySummaryActions';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sales tax liability summary header.
|
||||||
|
*/
|
||||||
|
function SalesTaxLiabilitySummaryHeader({
|
||||||
|
// #ownProps
|
||||||
|
onSubmitFilter,
|
||||||
|
pageFilter,
|
||||||
|
|
||||||
|
// #withSalesTaxLiabilitySummary
|
||||||
|
salesTaxLiabilitySummaryFilter,
|
||||||
|
|
||||||
|
// #withSalesTaxLiabilitySummaryActions
|
||||||
|
toggleSalesTaxLiabilitySummaryFilterDrawer: toggleFilterDrawer,
|
||||||
|
}) {
|
||||||
|
const defaultValues = getDefaultSalesTaxLiablitySummaryQuery();
|
||||||
|
|
||||||
|
// Filter form initial values.
|
||||||
|
const initialValues = transformToForm(
|
||||||
|
{
|
||||||
|
...defaultValues,
|
||||||
|
...pageFilter,
|
||||||
|
fromDate: moment(pageFilter.fromDate).toDate(),
|
||||||
|
toDate: moment(pageFilter.toDate).toDate(),
|
||||||
|
},
|
||||||
|
defaultValues,
|
||||||
|
);
|
||||||
|
// Validation schema.
|
||||||
|
const validationSchema = getSalesTaxLiabilitySummaryQueryValidation();
|
||||||
|
|
||||||
|
// Handle form submit.
|
||||||
|
const handleSubmit = (values, actions) => {
|
||||||
|
onSubmitFilter(values);
|
||||||
|
toggleFilterDrawer(false);
|
||||||
|
actions.setSubmitting(false);
|
||||||
|
};
|
||||||
|
// Handle cancel button click.
|
||||||
|
const handleCancelClick = () => {
|
||||||
|
toggleFilterDrawer(false);
|
||||||
|
};
|
||||||
|
// Handle drawer close action.
|
||||||
|
const handleDrawerClose = () => {
|
||||||
|
toggleFilterDrawer(false);
|
||||||
|
};
|
||||||
|
// Detarmines the given feature whether is enabled.
|
||||||
|
const { featureCan } = useFeatureCan();
|
||||||
|
const isBranchesFeatureCan = featureCan(Features.Branches);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BalanceSheetFinancialHeader
|
||||||
|
isOpen={salesTaxLiabilitySummaryFilter}
|
||||||
|
drawerProps={{
|
||||||
|
onClose: handleDrawerClose,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Formik
|
||||||
|
initialValues={initialValues}
|
||||||
|
validationSchema={validationSchema}
|
||||||
|
onSubmit={handleSubmit}
|
||||||
|
>
|
||||||
|
<Form>
|
||||||
|
{/* <Tabs animate={true} vertical={true} renderActiveTabPanelOnly={true}>
|
||||||
|
<Tab
|
||||||
|
id="general"
|
||||||
|
title={<T id={'general'} />}
|
||||||
|
panel={<BalanceSheetHeaderGeneralPanal />}
|
||||||
|
/>
|
||||||
|
</Tabs> */}
|
||||||
|
|
||||||
|
<div class="financial-header-drawer__footer">
|
||||||
|
<Button className={'mr1'} intent={Intent.PRIMARY} type={'submit'}>
|
||||||
|
<T id={'calculate_report'} />
|
||||||
|
</Button>
|
||||||
|
<Button onClick={handleCancelClick} minimal={true}>
|
||||||
|
<T id={'cancel'} />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Form>
|
||||||
|
</Formik>
|
||||||
|
</BalanceSheetFinancialHeader>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default compose(
|
||||||
|
withSalesTaxLiabilitySummary(({ salesTaxLiabilitySummaryFilter }) => ({
|
||||||
|
salesTaxLiabilitySummaryFilter,
|
||||||
|
})),
|
||||||
|
withSalesTaxLiabilitySummaryActions,
|
||||||
|
)(SalesTaxLiabilitySummaryHeader);
|
||||||
|
|
||||||
|
const BalanceSheetFinancialHeader = styled(FinancialStatementHeader)`
|
||||||
|
.bp3-drawer {
|
||||||
|
max-height: 520px;
|
||||||
|
}
|
||||||
|
`;
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import React from 'react';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
import intl from 'react-intl-universal';
|
||||||
|
|
||||||
|
import { TableStyle } from '@/constants';
|
||||||
|
import { ReportDataTable, FinancialSheet } from '@/components';
|
||||||
|
import { defaultExpanderReducer, tableRowTypesToClassnames } from '@/utils';
|
||||||
|
import { useSalesTaxLiabilitySummaryContext } from './SalesTaxLiabilitySummaryBoot';
|
||||||
|
import withCurrentOrganization from '@/containers/Organization/withCurrentOrganization';
|
||||||
|
import { useSalesTaxLiabilitySummaryColumns } from './utils';
|
||||||
|
import { compose } from 'ramda';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Balance sheet table.
|
||||||
|
*/
|
||||||
|
function SalesTaxLiabilitySummaryTableRoot({
|
||||||
|
// #ownProps
|
||||||
|
organizationName,
|
||||||
|
}) {
|
||||||
|
// Balance sheet context.
|
||||||
|
const {
|
||||||
|
salesTaxLiabilitySummary: { table },
|
||||||
|
} = useSalesTaxLiabilitySummaryContext();
|
||||||
|
|
||||||
|
// Retrieve the database columns.
|
||||||
|
const columns = useSalesTaxLiabilitySummaryColumns();
|
||||||
|
|
||||||
|
// Retrieve default expanded rows of balance sheet.
|
||||||
|
const expandedRows = React.useMemo(
|
||||||
|
() => defaultExpanderReducer(table.rows, 3),
|
||||||
|
[table],
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FinancialSheet
|
||||||
|
companyName={organizationName}
|
||||||
|
sheetType={'Sales Tax Liability Summary'}
|
||||||
|
asDate={new Date()}
|
||||||
|
basis={''}
|
||||||
|
>
|
||||||
|
<SalesTaxLiabilitySummaryDataTable
|
||||||
|
columns={columns}
|
||||||
|
data={table.rows}
|
||||||
|
rowClassNames={tableRowTypesToClassnames}
|
||||||
|
noInitialFetch={true}
|
||||||
|
expandable={true}
|
||||||
|
expanded={expandedRows}
|
||||||
|
expandToggleColumn={1}
|
||||||
|
expandColumnSpace={0.8}
|
||||||
|
headerLoading={true}
|
||||||
|
sticky={true}
|
||||||
|
styleName={TableStyle.Constrant}
|
||||||
|
/>
|
||||||
|
</FinancialSheet>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const SalesTaxLiabilitySummaryDataTable = styled(ReportDataTable)`
|
||||||
|
.table {
|
||||||
|
.tbody .tr {
|
||||||
|
.td {
|
||||||
|
border-bottom: 0;
|
||||||
|
padding-top: 0.32rem;
|
||||||
|
padding-bottom: 0.32rem;
|
||||||
|
}
|
||||||
|
&:not(.no-results) {
|
||||||
|
.td {
|
||||||
|
border-bottom: 0;
|
||||||
|
padding-top: 0.4rem;
|
||||||
|
padding-bottom: 0.4rem;
|
||||||
|
}
|
||||||
|
&:not(:first-child) .td {
|
||||||
|
border-top: 1px solid transparent;
|
||||||
|
}
|
||||||
|
&.row_type--Total {
|
||||||
|
font-weight: 500;
|
||||||
|
|
||||||
|
.td {
|
||||||
|
border-top: 1px solid #bbb;
|
||||||
|
border-bottom: 3px double #333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const SalesTaxLiabilitySummaryTable = compose(
|
||||||
|
withCurrentOrganization(({ organization }) => ({
|
||||||
|
organizationName: organization.name,
|
||||||
|
})),
|
||||||
|
)(SalesTaxLiabilitySummaryTableRoot);
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { useSalesTaxLiabilitySummaryContext } from './SalesTaxLiabilitySummaryBoot';
|
||||||
|
import FinancialLoadingBar from '../FinancialLoadingBar';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Balance sheet loading bar.
|
||||||
|
*/
|
||||||
|
export function SalesTaxLiabilitySummaryLoadingBar() {
|
||||||
|
const { isFetching } = useSalesTaxLiabilitySummaryContext();
|
||||||
|
|
||||||
|
if (!isFetching) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return <FinancialLoadingBar />;
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import React, { useMemo } from 'react';
|
||||||
|
import * as R from 'ramda';
|
||||||
|
import { getColumnWidth } from '@/utils';
|
||||||
|
import { Align } from '@/constants';
|
||||||
|
|
||||||
|
const getTableCellValueAccessor = (index) => `cells[${index}].value`;
|
||||||
|
|
||||||
|
const taxNameAccessor = R.curry((data, column) => ({
|
||||||
|
key: column.key,
|
||||||
|
Header: column.label,
|
||||||
|
accessor: getTableCellValueAccessor(column.cell_index),
|
||||||
|
sticky: 'left',
|
||||||
|
width: 240,
|
||||||
|
textOverview: true,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const taxCodeAccessor = R.curry((data, column) => ({
|
||||||
|
key: column.key,
|
||||||
|
Header: column.label,
|
||||||
|
accessor: getTableCellValueAccessor(column.cell_index),
|
||||||
|
sticky: 'left',
|
||||||
|
width: 240,
|
||||||
|
textOverview: true,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const taxableAmountAccessor = R.curry((data, column) => {
|
||||||
|
const accessor = getTableCellValueAccessor(column.cell_index);
|
||||||
|
|
||||||
|
return {
|
||||||
|
Header: column.label,
|
||||||
|
id: column.key,
|
||||||
|
accessor: getTableCellValueAccessor(column.cell_index),
|
||||||
|
className: column.key,
|
||||||
|
width: getColumnWidth(data, accessor, { minWidth: 120 }),
|
||||||
|
align: Align.Right,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const dynamicColumnMapper = R.curry((data, column) => {
|
||||||
|
const taxNameAccessorColumn = taxNameAccessor(data);
|
||||||
|
const taxCodeAccessorColumn = taxCodeAccessor(data);
|
||||||
|
const taxableAmountColumn = taxableAmountAccessor(data);
|
||||||
|
|
||||||
|
return R.compose(
|
||||||
|
R.when(R.pathEq(['key'], 'taxName'), taxNameAccessorColumn),
|
||||||
|
R.when(R.pathEq(['key'], 'taxCode'), taxCodeAccessorColumn),
|
||||||
|
R.when(R.pathEq(['key'], 'taxableAmount'), taxableAmountColumn),
|
||||||
|
R.when(R.pathEq(['key'], 'taxRate'), taxableAmountColumn),
|
||||||
|
)(column);
|
||||||
|
});
|
||||||
|
|
||||||
|
export const salesTaxLiabilitySummaryDynamicColumns = (columns, data) => {
|
||||||
|
return R.map(dynamicColumnMapper(data), columns);
|
||||||
|
};
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import React from 'react';
|
||||||
|
import moment from 'moment';
|
||||||
|
import * as Yup from 'yup';
|
||||||
|
import { castArray } from 'lodash';
|
||||||
|
import intl from 'react-intl-universal';
|
||||||
|
import { transformToForm } from '@/utils';
|
||||||
|
import { useAppQueryString } from '@/hooks';
|
||||||
|
import { salesTaxLiabilitySummaryDynamicColumns } from './dynamicColumns';
|
||||||
|
import { useSalesTaxLiabilitySummaryContext } from './SalesTaxLiabilitySummaryBoot';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the default sales tax liability summary query.
|
||||||
|
* @returns {}
|
||||||
|
*/
|
||||||
|
export const getDefaultSalesTaxLiablitySummaryQuery = () => ({
|
||||||
|
fromDate: moment().startOf('month').format('YYYY-MM-DD'),
|
||||||
|
toDate: moment().format('YYYY-MM-DD'),
|
||||||
|
basis: 'cash',
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the sales tax liability summary query.
|
||||||
|
*/
|
||||||
|
const parseSalesTaxLiabilitySummaryQuery = (locationQuery) => {
|
||||||
|
const defaultQuery = getDefaultSalesTaxLiablitySummaryQuery();
|
||||||
|
|
||||||
|
const transformed = {
|
||||||
|
...defaultQuery,
|
||||||
|
...transformToForm(locationQuery, defaultQuery),
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
...transformed,
|
||||||
|
|
||||||
|
// Ensures the branches ids is always array.
|
||||||
|
branchesIds: castArray(transformed.branchesIds),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the sales tax liability summary query.
|
||||||
|
*/
|
||||||
|
export const useSalesTaxLiabilitySummaryQuery = () => {
|
||||||
|
// Retrieves location query.
|
||||||
|
const [locationQuery, setLocationQuery] = useAppQueryString();
|
||||||
|
|
||||||
|
// Merges the default filter query with location URL query.
|
||||||
|
const parsedQuery = React.useMemo(
|
||||||
|
() => parseSalesTaxLiabilitySummaryQuery(locationQuery),
|
||||||
|
[locationQuery],
|
||||||
|
);
|
||||||
|
return [parsedQuery, setLocationQuery];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the sales tax liability summary default query.
|
||||||
|
*/
|
||||||
|
export const getSalesTaxLiabilitySummaryDefaultQuery = () => {
|
||||||
|
return {
|
||||||
|
basic: 'cash',
|
||||||
|
fromDate: moment().toDate(),
|
||||||
|
toDate: moment().toDate(),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the sales tax liability summary query validation.
|
||||||
|
*/
|
||||||
|
export const getSalesTaxLiabilitySummaryQueryValidation = () =>
|
||||||
|
Yup.object().shape({
|
||||||
|
dateRange: Yup.string().optional(),
|
||||||
|
fromDate: Yup.date().required().label(intl.get('fromDate')),
|
||||||
|
toDate: Yup.date()
|
||||||
|
.min(Yup.ref('fromDate'))
|
||||||
|
.required()
|
||||||
|
.label(intl.get('toDate')),
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the sales tax liability summary columns.
|
||||||
|
* @returns {ITableColumn[]}
|
||||||
|
*/
|
||||||
|
export const useSalesTaxLiabilitySummaryColumns = () => {
|
||||||
|
const {
|
||||||
|
salesTaxLiabilitySummary: { table },
|
||||||
|
} = useSalesTaxLiabilitySummaryContext();
|
||||||
|
|
||||||
|
return salesTaxLiabilitySummaryDynamicColumns(table.columns, table.rows);
|
||||||
|
};
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { getSalesTaxLiabilitySummaryFilterDrawer } from '@/store/financialStatement/financialStatements.selectors';
|
||||||
|
|
||||||
|
export default (mapState) => {
|
||||||
|
const mapStateToProps = (state, props) => {
|
||||||
|
const mapped = {
|
||||||
|
salesTaxLiabilitySummaryFilter:
|
||||||
|
getSalesTaxLiabilitySummaryFilterDrawer(state),
|
||||||
|
};
|
||||||
|
return mapState ? mapState(mapped, state, props) : mapped;
|
||||||
|
};
|
||||||
|
|
||||||
|
return connect(mapStateToProps);
|
||||||
|
};
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { toggleBalanceSheetFilterDrawer } from '@/store/financialStatement/financialStatements.actions';
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
toggleSalesTaxLiabilitySummaryFilterDrawer: (toggle) =>
|
||||||
|
dispatch(toggleBalanceSheetFilterDrawer(toggle)),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(null, mapDispatchToProps);
|
||||||
@@ -444,3 +444,25 @@ export function useTransactionsByReference(query, props) {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export function useSalesTaxLiabilitySummary(query, props) {
|
||||||
|
return useRequestQuery(
|
||||||
|
[t.FINANCIAL_REPORT, t.BALANCE_SHEET, query],
|
||||||
|
{
|
||||||
|
method: 'get',
|
||||||
|
url: '/financial_statements/sales-tax-liability-summary',
|
||||||
|
params: query,
|
||||||
|
headers: {
|
||||||
|
Accept: 'application/json+table',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
select: (res) => res.data,
|
||||||
|
...props,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -440,7 +440,9 @@ export const getDashboardRoutes = () => [
|
|||||||
path: `/financial-reports/project-profitability-summary`,
|
path: `/financial-reports/project-profitability-summary`,
|
||||||
component: lazy(
|
component: lazy(
|
||||||
() =>
|
() =>
|
||||||
import('@/containers/FinancialStatements/ProjectProfitabilitySummary/ProjectProfitabilitySummary'),
|
import(
|
||||||
|
'@/containers/FinancialStatements/ProjectProfitabilitySummary/ProjectProfitabilitySummary'
|
||||||
|
),
|
||||||
),
|
),
|
||||||
breadcrumb: intl.get('project_profitability_summary'),
|
breadcrumb: intl.get('project_profitability_summary'),
|
||||||
pageTitle: intl.get('project_profitability_summary'),
|
pageTitle: intl.get('project_profitability_summary'),
|
||||||
@@ -448,6 +450,20 @@ export const getDashboardRoutes = () => [
|
|||||||
sidebarExpand: false,
|
sidebarExpand: false,
|
||||||
subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
|
subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/financial-reports/sales-tax-liability-summary',
|
||||||
|
component: lazy(
|
||||||
|
() =>
|
||||||
|
import(
|
||||||
|
'@/containers/FinancialStatements/SalesTaxLiabilitySummary/SalesTaxLiabilitySummary'
|
||||||
|
),
|
||||||
|
),
|
||||||
|
breadcrumb: 'Sales Tax Liability Summary',
|
||||||
|
pageTitle: 'Sales Tax Liability Summary',
|
||||||
|
backLink: true,
|
||||||
|
sidebarExpand: false,
|
||||||
|
subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/financial-reports',
|
path: '/financial-reports',
|
||||||
component: lazy(
|
component: lazy(
|
||||||
|
|||||||
@@ -86,6 +86,10 @@ export const projectProfitabilitySummaryFilterDrawerSelector = (state) => {
|
|||||||
return filterDrawerByTypeSelector('projectProfitabilitySummary')(state);
|
return filterDrawerByTypeSelector('projectProfitabilitySummary')(state);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const salesTaxLiabilitySummaryFilterDrawerSelector = (state) => {
|
||||||
|
return filterDrawerByTypeSelector('projectProfitabilitySummary')(state);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve balance sheet filter drawer.
|
* Retrieve balance sheet filter drawer.
|
||||||
*/
|
*/
|
||||||
@@ -278,3 +282,11 @@ export const getProjectProfitabilitySummaryFilterDrawer = createSelector(
|
|||||||
return isOpen;
|
return isOpen;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve sales tax liability summary filter drawer.
|
||||||
|
*/
|
||||||
|
export const getSalesTaxLiabilitySummaryFilterDrawer = createSelector(
|
||||||
|
salesTaxLiabilitySummaryFilterDrawerSelector,
|
||||||
|
(isOpen) => isOpen,
|
||||||
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user