mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-20 14:50:32 +00:00
Merge pull request #564 from bigcapitalhq/fix-banking-bugs
fix: Banking service bugs
This commit is contained in:
@@ -20,6 +20,7 @@ export default class UncategorizedCashflowTransaction extends mixin(
|
|||||||
description!: string;
|
description!: string;
|
||||||
plaidTransactionId!: string;
|
plaidTransactionId!: string;
|
||||||
recognizedTransactionId!: number;
|
recognizedTransactionId!: number;
|
||||||
|
excludedAt: Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Table name.
|
* Table name.
|
||||||
@@ -45,6 +46,7 @@ export default class UncategorizedCashflowTransaction extends mixin(
|
|||||||
'isDepositTransaction',
|
'isDepositTransaction',
|
||||||
'isWithdrawalTransaction',
|
'isWithdrawalTransaction',
|
||||||
'isRecognized',
|
'isRecognized',
|
||||||
|
'isExcluded'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,6 +91,14 @@ export default class UncategorizedCashflowTransaction extends mixin(
|
|||||||
return !!this.recognizedTransactionId;
|
return !!this.recognizedTransactionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detarmines whether the transaction is excluded.
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
public get isExcluded(): boolean {
|
||||||
|
return !!this.excludedAt;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Model modifiers.
|
* Model modifiers.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Inject, Service } from 'typedi';
|
import { Inject, Service } from 'typedi';
|
||||||
import { initialize } from 'objection';
|
import { initialize } from 'objection';
|
||||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
import { UncategorizedTransactionTransformer } from '@/services/Cashflow/UncategorizedTransactionTransformer';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class GetBankAccountSummary {
|
export class GetBankAccountSummary {
|
||||||
@@ -31,17 +32,21 @@ export class GetBankAccountSummary {
|
|||||||
.findById(bankAccountId)
|
.findById(bankAccountId)
|
||||||
.throwIfNotFound();
|
.throwIfNotFound();
|
||||||
|
|
||||||
|
const commonQuery = (q) => {
|
||||||
|
// Include just the given account.
|
||||||
|
q.where('accountId', bankAccountId);
|
||||||
|
|
||||||
|
// Only the not excluded.
|
||||||
|
q.modify('notExcluded');
|
||||||
|
|
||||||
|
// Only the not categorized.
|
||||||
|
q.modify('notCategorized');
|
||||||
|
};
|
||||||
|
|
||||||
// Retrieves the uncategorized transactions count of the given bank account.
|
// Retrieves the uncategorized transactions count of the given bank account.
|
||||||
const uncategorizedTranasctionsCount =
|
const uncategorizedTranasctionsCount =
|
||||||
await UncategorizedCashflowTransaction.query().onBuild((q) => {
|
await UncategorizedCashflowTransaction.query().onBuild((q) => {
|
||||||
// Include just the given account.
|
commonQuery(q);
|
||||||
q.where('accountId', bankAccountId);
|
|
||||||
|
|
||||||
// Only the not excluded.
|
|
||||||
q.modify('notExcluded');
|
|
||||||
|
|
||||||
// Only the not categorized.
|
|
||||||
q.modify('notCategorized');
|
|
||||||
|
|
||||||
// Only the not matched bank transactions.
|
// Only the not matched bank transactions.
|
||||||
q.withGraphJoined('matchedBankTransactions');
|
q.withGraphJoined('matchedBankTransactions');
|
||||||
@@ -52,25 +57,40 @@ export class GetBankAccountSummary {
|
|||||||
q.first();
|
q.first();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Retrieves the recognized transactions count of the given bank account.
|
// Retrives the recognized transactions count.
|
||||||
const recognizedTransactionsCount = await RecognizedBankTransaction.query()
|
const recognizedTransactionsCount =
|
||||||
.whereExists(
|
await UncategorizedCashflowTransaction.query().onBuild((q) => {
|
||||||
UncategorizedCashflowTransaction.query().where(
|
commonQuery(q);
|
||||||
'accountId',
|
|
||||||
bankAccountId
|
q.withGraphJoined('recognizedTransaction');
|
||||||
)
|
q.whereNotNull('recognizedTransaction.id');
|
||||||
)
|
|
||||||
.count('id as total')
|
// Count the results.
|
||||||
.first();
|
q.count('uncategorized_cashflow_transactions.id as total');
|
||||||
|
q.first();
|
||||||
|
});
|
||||||
|
|
||||||
|
const excludedTransactionsCount =
|
||||||
|
await UncategorizedCashflowTransaction.query().onBuild((q) => {
|
||||||
|
q.where('accountId', bankAccountId);
|
||||||
|
q.modify('excluded');
|
||||||
|
|
||||||
|
// Count the results.
|
||||||
|
q.count('uncategorized_cashflow_transactions.id as total');
|
||||||
|
q.first();
|
||||||
|
});
|
||||||
|
|
||||||
const totalUncategorizedTransactions =
|
const totalUncategorizedTransactions =
|
||||||
uncategorizedTranasctionsCount?.total || 0;
|
uncategorizedTranasctionsCount?.total || 0;
|
||||||
const totalRecognizedTransactions = recognizedTransactionsCount?.total || 0;
|
const totalRecognizedTransactions = recognizedTransactionsCount?.total || 0;
|
||||||
|
|
||||||
|
const totalExcludedTransactions = excludedTransactionsCount?.total || 0;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: bankAccount.name,
|
name: bankAccount.name,
|
||||||
totalUncategorizedTransactions,
|
totalUncategorizedTransactions,
|
||||||
totalRecognizedTransactions,
|
totalRecognizedTransactions,
|
||||||
|
totalExcludedTransactions,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
|
import { Knex } from 'knex';
|
||||||
|
import { Inject, Service } from 'typedi';
|
||||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
import UnitOfWork from '@/services/UnitOfWork';
|
import UnitOfWork from '@/services/UnitOfWork';
|
||||||
import { Inject, Service } from 'typedi';
|
import {
|
||||||
import { validateTransactionNotCategorized } from './utils';
|
validateTransactionNotCategorized,
|
||||||
|
validateTransactionNotExcluded,
|
||||||
|
} from './utils';
|
||||||
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
|
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
|
||||||
import events from '@/subscribers/events';
|
import events from '@/subscribers/events';
|
||||||
import {
|
import {
|
||||||
@@ -37,9 +41,13 @@ export class ExcludeBankTransaction {
|
|||||||
.findById(uncategorizedTransactionId)
|
.findById(uncategorizedTransactionId)
|
||||||
.throwIfNotFound();
|
.throwIfNotFound();
|
||||||
|
|
||||||
|
// Validate the transaction shouldn't be excluded.
|
||||||
|
validateTransactionNotExcluded(oldUncategorizedTransaction);
|
||||||
|
|
||||||
|
// Validate the transaction shouldn't be categorized.
|
||||||
validateTransactionNotCategorized(oldUncategorizedTransaction);
|
validateTransactionNotCategorized(oldUncategorizedTransaction);
|
||||||
|
|
||||||
return this.uow.withTransaction(tenantId, async (trx) => {
|
return this.uow.withTransaction(tenantId, async (trx: Knex.Transaction) => {
|
||||||
await this.eventPublisher.emitAsync(events.bankTransactions.onExcluding, {
|
await this.eventPublisher.emitAsync(events.bankTransactions.onExcluding, {
|
||||||
tenantId,
|
tenantId,
|
||||||
uncategorizedTransactionId,
|
uncategorizedTransactionId,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Inject, Service } from 'typedi';
|
import { Inject, Service } from 'typedi';
|
||||||
import PromisePool from '@supercharge/promise-pool';
|
import PromisePool from '@supercharge/promise-pool';
|
||||||
import { castArray } from 'lodash';
|
import { castArray, uniq } from 'lodash';
|
||||||
import { ExcludeBankTransaction } from './ExcludeBankTransaction';
|
import { ExcludeBankTransaction } from './ExcludeBankTransaction';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
@@ -18,7 +18,7 @@ export class ExcludeBankTransactions {
|
|||||||
tenantId: number,
|
tenantId: number,
|
||||||
bankTransactionIds: Array<number> | number
|
bankTransactionIds: Array<number> | number
|
||||||
) {
|
) {
|
||||||
const _bankTransactionIds = castArray(bankTransactionIds);
|
const _bankTransactionIds = uniq(castArray(bankTransactionIds));
|
||||||
|
|
||||||
await PromisePool.withConcurrency(1)
|
await PromisePool.withConcurrency(1)
|
||||||
.for(_bankTransactionIds)
|
.for(_bankTransactionIds)
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
|
import { Knex } from 'knex';
|
||||||
|
import { Inject, Service } from 'typedi';
|
||||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
import UnitOfWork from '@/services/UnitOfWork';
|
import UnitOfWork from '@/services/UnitOfWork';
|
||||||
import { Inject, Service } from 'typedi';
|
import {
|
||||||
import { validateTransactionNotCategorized } from './utils';
|
validateTransactionNotCategorized,
|
||||||
|
validateTransactionShouldBeExcluded,
|
||||||
|
} from './utils';
|
||||||
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
|
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
|
||||||
import events from '@/subscribers/events';
|
import events from '@/subscribers/events';
|
||||||
import {
|
import {
|
||||||
@@ -37,9 +41,13 @@ export class UnexcludeBankTransaction {
|
|||||||
.findById(uncategorizedTransactionId)
|
.findById(uncategorizedTransactionId)
|
||||||
.throwIfNotFound();
|
.throwIfNotFound();
|
||||||
|
|
||||||
|
// Validate the transaction should be excludded.
|
||||||
|
validateTransactionShouldBeExcluded(oldUncategorizedTransaction);
|
||||||
|
|
||||||
|
// Validate the transaction shouldn't be categorized.
|
||||||
validateTransactionNotCategorized(oldUncategorizedTransaction);
|
validateTransactionNotCategorized(oldUncategorizedTransaction);
|
||||||
|
|
||||||
return this.uow.withTransaction(tenantId, async (trx) => {
|
return this.uow.withTransaction(tenantId, async (trx: Knex.Transaction) => {
|
||||||
await this.eventPublisher.emitAsync(
|
await this.eventPublisher.emitAsync(
|
||||||
events.bankTransactions.onUnexcluding,
|
events.bankTransactions.onUnexcluding,
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Inject, Service } from 'typedi';
|
import { Inject, Service } from 'typedi';
|
||||||
import PromisePool from '@supercharge/promise-pool';
|
import PromisePool from '@supercharge/promise-pool';
|
||||||
import { UnexcludeBankTransaction } from './UnexcludeBankTransaction';
|
import { UnexcludeBankTransaction } from './UnexcludeBankTransaction';
|
||||||
import { castArray } from 'lodash';
|
import { castArray, uniq } from 'lodash';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class UnexcludeBankTransactions {
|
export class UnexcludeBankTransactions {
|
||||||
@@ -17,7 +17,7 @@ export class UnexcludeBankTransactions {
|
|||||||
tenantId: number,
|
tenantId: number,
|
||||||
bankTransactionIds: Array<number> | number
|
bankTransactionIds: Array<number> | number
|
||||||
) {
|
) {
|
||||||
const _bankTransactionIds = castArray(bankTransactionIds);
|
const _bankTransactionIds = uniq(castArray(bankTransactionIds));
|
||||||
|
|
||||||
await PromisePool.withConcurrency(1)
|
await PromisePool.withConcurrency(1)
|
||||||
.for(_bankTransactionIds)
|
.for(_bankTransactionIds)
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import UncategorizedCashflowTransaction from '@/models/UncategorizedCashflowTran
|
|||||||
|
|
||||||
const ERRORS = {
|
const ERRORS = {
|
||||||
TRANSACTION_ALREADY_CATEGORIZED: 'TRANSACTION_ALREADY_CATEGORIZED',
|
TRANSACTION_ALREADY_CATEGORIZED: 'TRANSACTION_ALREADY_CATEGORIZED',
|
||||||
|
TRANSACTION_ALREADY_EXCLUDED: 'TRANSACTION_ALREADY_EXCLUDED',
|
||||||
|
TRANSACTION_NOT_EXCLUDED: 'TRANSACTION_NOT_EXCLUDED',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const validateTransactionNotCategorized = (
|
export const validateTransactionNotCategorized = (
|
||||||
@@ -12,3 +14,19 @@ export const validateTransactionNotCategorized = (
|
|||||||
throw new ServiceError(ERRORS.TRANSACTION_ALREADY_CATEGORIZED);
|
throw new ServiceError(ERRORS.TRANSACTION_ALREADY_CATEGORIZED);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const validateTransactionNotExcluded = (
|
||||||
|
transaction: UncategorizedCashflowTransaction
|
||||||
|
) => {
|
||||||
|
if (transaction.isExcluded) {
|
||||||
|
throw new ServiceError(ERRORS.TRANSACTION_ALREADY_EXCLUDED);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const validateTransactionShouldBeExcluded = (
|
||||||
|
transaction: UncategorizedCashflowTransaction
|
||||||
|
) => {
|
||||||
|
if (!transaction.isExcluded) {
|
||||||
|
throw new ServiceError(ERRORS.TRANSACTION_NOT_EXCLUDED);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ export class GetRecognizedTransactionsService {
|
|||||||
q.withGraphFetched('recognizedTransaction.assignAccount');
|
q.withGraphFetched('recognizedTransaction.assignAccount');
|
||||||
q.withGraphFetched('recognizedTransaction.bankRule');
|
q.withGraphFetched('recognizedTransaction.bankRule');
|
||||||
q.whereNotNull('recognizedTransactionId');
|
q.whereNotNull('recognizedTransactionId');
|
||||||
|
q.modify('notExcluded');
|
||||||
|
|
||||||
if (_filter.accountId) {
|
if (_filter.accountId) {
|
||||||
q.where('accountId', _filter.accountId);
|
q.where('accountId', _filter.accountId);
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
import React from 'react';
|
// @ts-nocheck
|
||||||
import { AppShellProvider, useAppShellContext } from './AppContentShellProvider';
|
import React, { forwardRef, Ref } from 'react';
|
||||||
|
import {
|
||||||
|
AppShellProvider,
|
||||||
|
useAppShellContext,
|
||||||
|
} from './AppContentShellProvider';
|
||||||
import { Box, BoxProps } from '../../Layout';
|
import { Box, BoxProps } from '../../Layout';
|
||||||
import styles from './AppContentShell.module.scss';
|
import styles from './AppContentShell.module.scss';
|
||||||
|
|
||||||
@@ -12,50 +16,73 @@ interface AppContentShellProps {
|
|||||||
hideMain?: boolean;
|
hideMain?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function AppContentShell({
|
export const AppContentShell = forwardRef(
|
||||||
asideProps,
|
(
|
||||||
mainProps,
|
{
|
||||||
topbarOffset = 0,
|
asideProps,
|
||||||
hideAside = false,
|
mainProps,
|
||||||
hideMain = false,
|
topbarOffset = 0,
|
||||||
...restProps
|
hideAside = false,
|
||||||
}: AppContentShellProps) {
|
hideMain = false,
|
||||||
return (
|
...restProps
|
||||||
<AppShellProvider
|
}: AppContentShellProps,
|
||||||
mainProps={mainProps}
|
ref: Ref<HTMLDivElement>,
|
||||||
asideProps={asideProps}
|
) => {
|
||||||
topbarOffset={topbarOffset}
|
return (
|
||||||
hideAside={hideAside}
|
<AppShellProvider
|
||||||
hideMain={hideMain}
|
mainProps={mainProps}
|
||||||
>
|
asideProps={asideProps}
|
||||||
<Box {...restProps} className={styles.root} />
|
topbarOffset={topbarOffset}
|
||||||
</AppShellProvider>
|
hideAside={hideAside}
|
||||||
);
|
hideMain={hideMain}
|
||||||
}
|
>
|
||||||
|
<Box {...restProps} className={styles.root} ref={ref} />
|
||||||
|
</AppShellProvider>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
AppContentShell.displayName = 'AppContentShell';
|
||||||
|
|
||||||
interface AppContentShellMainProps extends BoxProps {}
|
interface AppContentShellMainProps extends BoxProps {}
|
||||||
|
|
||||||
function AppContentShellMain({ ...props }: AppContentShellMainProps) {
|
/**
|
||||||
const { hideMain } = useAppShellContext();
|
* Main content of the app shell.
|
||||||
|
* @param {AppContentShellMainProps} props -
|
||||||
|
* @returns {React.ReactNode}
|
||||||
|
*/
|
||||||
|
const AppContentShellMain = forwardRef(
|
||||||
|
({ ...props }: AppContentShellMainProps, ref: Ref<HTMLDivElement>) => {
|
||||||
|
const { hideMain } = useAppShellContext();
|
||||||
|
|
||||||
if (hideMain === true) {
|
if (hideMain === true) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return <Box {...props} className={styles.main} />;
|
return <Box {...props} className={styles.main} ref={ref} />;
|
||||||
}
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
AppContentShellMain.displayName = 'AppContentShellMain';
|
||||||
|
|
||||||
interface AppContentShellAsideProps extends BoxProps {
|
interface AppContentShellAsideProps extends BoxProps {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
function AppContentShellAside({ ...props }: AppContentShellAsideProps) {
|
/**
|
||||||
const { hideAside } = useAppShellContext();
|
* Aside content of the app shell.
|
||||||
|
* @param {AppContentShellAsideProps} props
|
||||||
|
* @returns {React.ReactNode}
|
||||||
|
*/
|
||||||
|
const AppContentShellAside = forwardRef(
|
||||||
|
({ ...props }: AppContentShellAsideProps, ref: Ref<HTMLDivElement>) => {
|
||||||
|
const { hideAside } = useAppShellContext();
|
||||||
|
|
||||||
if (hideAside === true) {
|
if (hideAside === true) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return <Box {...props} className={styles.aside} />;
|
return <Box {...props} className={styles.aside} ref={ref} />;
|
||||||
}
|
},
|
||||||
|
);
|
||||||
|
AppContentShellAside.displayName = 'AppContentShellAside';
|
||||||
|
|
||||||
AppContentShell.Main = AppContentShellMain;
|
AppContentShell.Main = AppContentShellMain;
|
||||||
AppContentShell.Aside = AppContentShellAside;
|
AppContentShell.Aside = AppContentShellAside;
|
||||||
|
|||||||
@@ -25,14 +25,13 @@ function TableVirtualizedListRow({ index, isScrolling, isVisible, style }) {
|
|||||||
export function TableVirtualizedListRows() {
|
export function TableVirtualizedListRows() {
|
||||||
const {
|
const {
|
||||||
table: { page },
|
table: { page },
|
||||||
props: { vListrowHeight, vListOverscanRowCount },
|
props: { vListrowHeight, vListOverscanRowCount, windowScrollerProps },
|
||||||
} = useContext(TableContext);
|
} = useContext(TableContext);
|
||||||
|
|
||||||
// Dashboard content pane.
|
// Dashboard content pane.
|
||||||
const dashboardContentPane = React.useMemo(
|
const scrollElement =
|
||||||
() => document.querySelector(`.${CLASSES.DASHBOARD_CONTENT_PANE}`),
|
windowScrollerProps?.scrollElement ||
|
||||||
[],
|
document.querySelector(`.${CLASSES.DASHBOARD_CONTENT_PANE}`);
|
||||||
);
|
|
||||||
|
|
||||||
const rowRenderer = React.useCallback(
|
const rowRenderer = React.useCallback(
|
||||||
({ key, ...args }) => <TableVirtualizedListRow {...args} key={key} />,
|
({ key, ...args }) => <TableVirtualizedListRow {...args} key={key} />,
|
||||||
@@ -40,7 +39,7 @@ export function TableVirtualizedListRows() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WindowScroller scrollElement={dashboardContentPane}>
|
<WindowScroller scrollElement={scrollElement}>
|
||||||
{({ height, isScrolling, onChildScroll, scrollTop }) => (
|
{({ height, isScrolling, onChildScroll, scrollTop }) => (
|
||||||
<AutoSizer disableHeight>
|
<AutoSizer disableHeight>
|
||||||
{({ width }) => (
|
{({ width }) => (
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
import React from 'react';
|
import React, { forwardRef, Ref } from 'react';
|
||||||
import { HTMLDivProps, Props } from '@blueprintjs/core';
|
import { HTMLDivProps, Props } from '@blueprintjs/core';
|
||||||
|
|
||||||
export interface BoxProps extends Props, HTMLDivProps {
|
export interface BoxProps extends Props, HTMLDivProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Box({ className, ...rest }: BoxProps) {
|
export const Box = forwardRef(
|
||||||
const Element = 'div';
|
({ className, ...rest }: BoxProps, ref: Ref<HTMLDivElement>) => {
|
||||||
|
const Element = 'div';
|
||||||
|
|
||||||
return <Element className={className} {...rest} />;
|
return <Element className={className} ref={ref} {...rest} />;
|
||||||
}
|
},
|
||||||
|
);
|
||||||
|
Box.displayName = '@bigcapital/Box';
|
||||||
|
|||||||
10
packages/webapp/src/constants/query-keys/banking.ts
Normal file
10
packages/webapp/src/constants/query-keys/banking.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
export const BANK_QUERY_KEY = {
|
||||||
|
BANK_RULES: 'BANK_RULE',
|
||||||
|
BANK_TRANSACTION_MATCHES: 'BANK_TRANSACTION_MATCHES',
|
||||||
|
RECOGNIZED_BANK_TRANSACTION: 'RECOGNIZED_BANK_TRANSACTION',
|
||||||
|
EXCLUDED_BANK_TRANSACTIONS_INFINITY: 'EXCLUDED_BANK_TRANSACTIONS_INFINITY',
|
||||||
|
RECOGNIZED_BANK_TRANSACTIONS_INFINITY:
|
||||||
|
'RECOGNIZED_BANK_TRANSACTIONS_INFINITY',
|
||||||
|
BANK_ACCOUNT_SUMMARY_META: 'BANK_ACCOUNT_SUMMARY_META',
|
||||||
|
AUTOFILL_CATEGORIZE_BANK_TRANSACTION: 'AUTOFILL_CATEGORIZE_BANK_TRANSACTION',
|
||||||
|
};
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
|
import { useMemo } from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { ContentTabs } from '@/components/ContentTabs/ContentTabs';
|
import { ContentTabs } from '@/components/ContentTabs/ContentTabs';
|
||||||
import { useAccountTransactionsContext } from './AccountTransactionsProvider';
|
import { useAccountTransactionsContext } from './AccountTransactionsProvider';
|
||||||
@@ -8,15 +9,19 @@ const AccountContentTabs = styled(ContentTabs)`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export function AccountTransactionsFilterTabs() {
|
export function AccountTransactionsFilterTabs() {
|
||||||
const { filterTab, setFilterTab, currentAccount } =
|
const { filterTab, setFilterTab, bankAccountMetaSummary, currentAccount } =
|
||||||
useAccountTransactionsContext();
|
useAccountTransactionsContext();
|
||||||
|
|
||||||
const handleChange = (value) => {
|
const handleChange = (value) => {
|
||||||
setFilterTab(value);
|
setFilterTab(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
const hasUncategorizedTransx = Boolean(
|
// Detarmines whether show the uncategorized transactions tab.
|
||||||
currentAccount.uncategorized_transactions,
|
const hasUncategorizedTransx = useMemo(
|
||||||
|
() =>
|
||||||
|
bankAccountMetaSummary?.totalUncategorizedTransactions > 0 ||
|
||||||
|
bankAccountMetaSummary?.totalExcludedTransactions > 0,
|
||||||
|
[bankAccountMetaSummary],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -29,28 +29,41 @@ function AccountTransactionsListRoot({
|
|||||||
return (
|
return (
|
||||||
<AccountTransactionsProvider>
|
<AccountTransactionsProvider>
|
||||||
<AppContentShell hideAside={!openMatchingTransactionAside}>
|
<AppContentShell hideAside={!openMatchingTransactionAside}>
|
||||||
<AppContentShell.Main>
|
<AccountTransactionsMain />
|
||||||
<AccountTransactionsActionsBar />
|
<AccountTransactionsAside />
|
||||||
<AccountTransactionsDetailsBar />
|
|
||||||
<AccountTransactionsProgressBar />
|
|
||||||
|
|
||||||
<DashboardPageContent>
|
|
||||||
<AccountTransactionsFilterTabs />
|
|
||||||
|
|
||||||
<Suspense fallback={<Spinner size={30} />}>
|
|
||||||
<AccountTransactionsContent />
|
|
||||||
</Suspense>
|
|
||||||
</DashboardPageContent>
|
|
||||||
</AppContentShell.Main>
|
|
||||||
|
|
||||||
<AppContentShell.Aside>
|
|
||||||
<CategorizeTransactionAside />
|
|
||||||
</AppContentShell.Aside>
|
|
||||||
</AppContentShell>
|
</AppContentShell>
|
||||||
</AccountTransactionsProvider>
|
</AccountTransactionsProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function AccountTransactionsMain() {
|
||||||
|
const { setScrollableRef } = useAccountTransactionsContext();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AppContentShell.Main ref={(e) => setScrollableRef(e)}>
|
||||||
|
<AccountTransactionsActionsBar />
|
||||||
|
<AccountTransactionsDetailsBar />
|
||||||
|
<AccountTransactionsProgressBar />
|
||||||
|
|
||||||
|
<DashboardPageContent>
|
||||||
|
<AccountTransactionsFilterTabs />
|
||||||
|
|
||||||
|
<Suspense fallback={<Spinner size={30} />}>
|
||||||
|
<AccountTransactionsContent />
|
||||||
|
</Suspense>
|
||||||
|
</DashboardPageContent>
|
||||||
|
</AppContentShell.Main>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function AccountTransactionsAside() {
|
||||||
|
return (
|
||||||
|
<AppContentShell.Aside>
|
||||||
|
<CategorizeTransactionAside />
|
||||||
|
</AppContentShell.Aside>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export default R.compose(
|
export default R.compose(
|
||||||
withBanking(
|
withBanking(
|
||||||
({ selectedUncategorizedTransactionId, openMatchingTransactionAside }) => ({
|
({ selectedUncategorizedTransactionId, openMatchingTransactionAside }) => ({
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
import React from 'react';
|
import React, { useRef, useState } from 'react';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { DashboardInsider } from '@/components';
|
import { DashboardInsider } from '@/components';
|
||||||
import { useCashflowAccounts, useAccount } from '@/hooks/query';
|
import { useCashflowAccounts, useAccount } from '@/hooks/query';
|
||||||
@@ -41,6 +41,8 @@ function AccountTransactionsProvider({ query, ...props }) {
|
|||||||
isLoading: isBankAccountMetaSummaryLoading,
|
isLoading: isBankAccountMetaSummaryLoading,
|
||||||
} = useGetBankAccountSummaryMeta(accountId);
|
} = useGetBankAccountSummaryMeta(accountId);
|
||||||
|
|
||||||
|
const [scrollableRef, setScrollableRef] = useState();
|
||||||
|
|
||||||
// Provider payload.
|
// Provider payload.
|
||||||
const provider = {
|
const provider = {
|
||||||
accountId,
|
accountId,
|
||||||
@@ -56,6 +58,9 @@ function AccountTransactionsProvider({ query, ...props }) {
|
|||||||
|
|
||||||
filterTab,
|
filterTab,
|
||||||
setFilterTab,
|
setFilterTab,
|
||||||
|
|
||||||
|
scrollableRef,
|
||||||
|
setScrollableRef
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import { TABLES } from '@/constants/tables';
|
|||||||
import { useMemorizedColumnsWidths } from '@/hooks';
|
import { useMemorizedColumnsWidths } from '@/hooks';
|
||||||
import { useExcludedTransactionsColumns } from './_utils';
|
import { useExcludedTransactionsColumns } from './_utils';
|
||||||
import { useExcludedTransactionsBoot } from './ExcludedTransactionsTableBoot';
|
import { useExcludedTransactionsBoot } from './ExcludedTransactionsTableBoot';
|
||||||
|
import { useAccountTransactionsContext } from '../AccountTransactionsProvider';
|
||||||
|
|
||||||
import { ActionsMenu } from './_components';
|
import { ActionsMenu } from './_components';
|
||||||
import { useUnexcludeUncategorizedTransaction } from '@/hooks/query/bank-rules';
|
import { useUnexcludeUncategorizedTransaction } from '@/hooks/query/bank-rules';
|
||||||
@@ -37,6 +38,8 @@ function ExcludedTransactionsTableRoot({
|
|||||||
const { mutateAsync: unexcludeBankTransaction } =
|
const { mutateAsync: unexcludeBankTransaction } =
|
||||||
useUnexcludeUncategorizedTransaction();
|
useUnexcludeUncategorizedTransaction();
|
||||||
|
|
||||||
|
const { scrollableRef } = useAccountTransactionsContext();
|
||||||
|
|
||||||
// Retrieve table columns.
|
// Retrieve table columns.
|
||||||
const columns = useExcludedTransactionsColumns();
|
const columns = useExcludedTransactionsColumns();
|
||||||
|
|
||||||
@@ -97,6 +100,7 @@ function ExcludedTransactionsTableRoot({
|
|||||||
className="table-constrant"
|
className="table-constrant"
|
||||||
selectionColumn={true}
|
selectionColumn={true}
|
||||||
onSelectedRowsChange={handleSelectedRowsChange}
|
onSelectedRowsChange={handleSelectedRowsChange}
|
||||||
|
windowScrollerProps={{ scrollElement: scrollableRef }}
|
||||||
payload={{
|
payload={{
|
||||||
onRestore: handleRestoreClick,
|
onRestore: handleRestoreClick,
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import { useRecognizedTransactionsBoot } from './RecognizedTransactionsTableBoot
|
|||||||
|
|
||||||
import { ActionsMenu } from './_components';
|
import { ActionsMenu } from './_components';
|
||||||
import { compose } from '@/utils';
|
import { compose } from '@/utils';
|
||||||
|
import { useAccountTransactionsContext } from '../AccountTransactionsProvider';
|
||||||
import { useExcludeUncategorizedTransaction } from '@/hooks/query/bank-rules';
|
import { useExcludeUncategorizedTransaction } from '@/hooks/query/bank-rules';
|
||||||
import {
|
import {
|
||||||
WithBankingActionsProps,
|
WithBankingActionsProps,
|
||||||
@@ -33,8 +34,8 @@ interface RecognizedTransactionsTableProps extends WithBankingActionsProps {}
|
|||||||
* Renders the recognized account transactions datatable.
|
* Renders the recognized account transactions datatable.
|
||||||
*/
|
*/
|
||||||
function RecognizedTransactionsTableRoot({
|
function RecognizedTransactionsTableRoot({
|
||||||
// #withBanking
|
// #withBankingActions
|
||||||
setUncategorizedTransactionIdForMatching,
|
setTransactionsToCategorizeSelected,
|
||||||
}: RecognizedTransactionsTableProps) {
|
}: RecognizedTransactionsTableProps) {
|
||||||
const { mutateAsync: excludeBankTransaction } =
|
const { mutateAsync: excludeBankTransaction } =
|
||||||
useExcludeUncategorizedTransaction();
|
useExcludeUncategorizedTransaction();
|
||||||
@@ -49,9 +50,11 @@ function RecognizedTransactionsTableRoot({
|
|||||||
const [initialColumnsWidths, , handleColumnResizing] =
|
const [initialColumnsWidths, , handleColumnResizing] =
|
||||||
useMemorizedColumnsWidths(TABLES.UNCATEGORIZED_ACCOUNT_TRANSACTIONS);
|
useMemorizedColumnsWidths(TABLES.UNCATEGORIZED_ACCOUNT_TRANSACTIONS);
|
||||||
|
|
||||||
|
const { scrollableRef } = useAccountTransactionsContext();
|
||||||
|
|
||||||
// Handle cell click.
|
// Handle cell click.
|
||||||
const handleCellClick = (cell, event) => {
|
const handleCellClick = (cell, event) => {
|
||||||
setUncategorizedTransactionIdForMatching(
|
setTransactionsToCategorizeSelected(
|
||||||
cell.row.original.uncategorized_transaction_id,
|
cell.row.original.uncategorized_transaction_id,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -74,7 +77,7 @@ function RecognizedTransactionsTableRoot({
|
|||||||
|
|
||||||
// Handles categorize button click.
|
// Handles categorize button click.
|
||||||
const handleCategorizeClick = (transaction) => {
|
const handleCategorizeClick = (transaction) => {
|
||||||
setUncategorizedTransactionIdForMatching(
|
setTransactionsToCategorizeSelected(
|
||||||
transaction.uncategorized_transaction_id,
|
transaction.uncategorized_transaction_id,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -102,6 +105,7 @@ function RecognizedTransactionsTableRoot({
|
|||||||
vListOverscanRowCount={0}
|
vListOverscanRowCount={0}
|
||||||
initialColumnsWidths={initialColumnsWidths}
|
initialColumnsWidths={initialColumnsWidths}
|
||||||
onColumnResizing={handleColumnResizing}
|
onColumnResizing={handleColumnResizing}
|
||||||
|
windowScrollerProps={{ scrollElement: scrollableRef }}
|
||||||
noResults={<RecognizedTransactionsTableNoResults />}
|
noResults={<RecognizedTransactionsTableNoResults />}
|
||||||
className="table-constrant"
|
className="table-constrant"
|
||||||
payload={{
|
payload={{
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import { useMemorizedColumnsWidths } from '@/hooks';
|
|||||||
import { useAccountUncategorizedTransactionsContext } from '../AllTransactionsUncategorizedBoot';
|
import { useAccountUncategorizedTransactionsContext } from '../AllTransactionsUncategorizedBoot';
|
||||||
import { useExcludeUncategorizedTransaction } from '@/hooks/query/bank-rules';
|
import { useExcludeUncategorizedTransaction } from '@/hooks/query/bank-rules';
|
||||||
import { useAccountUncategorizedTransactionsColumns } from './hooks';
|
import { useAccountUncategorizedTransactionsColumns } from './hooks';
|
||||||
|
import { useAccountTransactionsContext } from '../AccountTransactionsProvider';
|
||||||
|
|
||||||
import { compose } from '@/utils';
|
import { compose } from '@/utils';
|
||||||
import { withBanking } from '../../withBanking';
|
import { withBanking } from '../../withBanking';
|
||||||
@@ -48,6 +49,8 @@ function AccountTransactionsDataTable({
|
|||||||
// Retrieve table columns.
|
// Retrieve table columns.
|
||||||
const columns = useAccountUncategorizedTransactionsColumns();
|
const columns = useAccountUncategorizedTransactionsColumns();
|
||||||
|
|
||||||
|
const { scrollableRef } = useAccountTransactionsContext();
|
||||||
|
|
||||||
// Retrieve list context.
|
// Retrieve list context.
|
||||||
const { uncategorizedTransactions, isUncategorizedTransactionsLoading } =
|
const { uncategorizedTransactions, isUncategorizedTransactionsLoading } =
|
||||||
useAccountUncategorizedTransactionsContext();
|
useAccountUncategorizedTransactionsContext();
|
||||||
@@ -71,6 +74,11 @@ function AccountTransactionsDataTable({
|
|||||||
const handleCategorizeBtnClick = (transaction) => {
|
const handleCategorizeBtnClick = (transaction) => {
|
||||||
setUncategorizedTransactionIdForMatching(transaction.id);
|
setUncategorizedTransactionIdForMatching(transaction.id);
|
||||||
};
|
};
|
||||||
|
// handles table selected rows change.
|
||||||
|
const handleSelectedRowsChange = (selected) => {
|
||||||
|
const transactionIds = selected.map((r) => r.original.id);
|
||||||
|
setUncategorizedTransactionsSelected(transactionIds);
|
||||||
|
};
|
||||||
// Handle exclude transaction.
|
// Handle exclude transaction.
|
||||||
const handleExcludeTransaction = (transaction) => {
|
const handleExcludeTransaction = (transaction) => {
|
||||||
excludeTransaction(transaction.id)
|
excludeTransaction(transaction.id)
|
||||||
@@ -118,6 +126,8 @@ function AccountTransactionsDataTable({
|
|||||||
onExclude: handleExcludeTransaction,
|
onExclude: handleExcludeTransaction,
|
||||||
onCategorize: handleCategorizeBtnClick,
|
onCategorize: handleCategorizeBtnClick,
|
||||||
}}
|
}}
|
||||||
|
onSelectedRowsChange={handleSelectedRowsChange}
|
||||||
|
windowScrollerProps={{ scrollElement: scrollableRef }}
|
||||||
className={clsx('table-constrant', styles.table, {
|
className={clsx('table-constrant', styles.table, {
|
||||||
[styles.showCategorizeColumn]: enableMultipleCategorization,
|
[styles.showCategorizeColumn]: enableMultipleCategorization,
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -13,21 +13,12 @@ import {
|
|||||||
import useApiRequest from '../useRequest';
|
import useApiRequest from '../useRequest';
|
||||||
import { transformToCamelCase } from '@/utils';
|
import { transformToCamelCase } from '@/utils';
|
||||||
import t from './types';
|
import t from './types';
|
||||||
|
import { BANK_QUERY_KEY } from '@/constants/query-keys/banking';
|
||||||
|
|
||||||
const QUERY_KEY = {
|
// Common cache invalidator.
|
||||||
BANK_RULES: 'BANK_RULE',
|
|
||||||
BANK_TRANSACTION_MATCHES: 'BANK_TRANSACTION_MATCHES',
|
|
||||||
RECOGNIZED_BANK_TRANSACTION: 'RECOGNIZED_BANK_TRANSACTION',
|
|
||||||
EXCLUDED_BANK_TRANSACTIONS_INFINITY: 'EXCLUDED_BANK_TRANSACTIONS_INFINITY',
|
|
||||||
RECOGNIZED_BANK_TRANSACTIONS_INFINITY:
|
|
||||||
'RECOGNIZED_BANK_TRANSACTIONS_INFINITY',
|
|
||||||
BANK_ACCOUNT_SUMMARY_META: 'BANK_ACCOUNT_SUMMARY_META',
|
|
||||||
AUTOFILL_CATEGORIZE_BANK_TRANSACTION: 'AUTOFILL_CATEGORIZE_BANK_TRANSACTION',
|
|
||||||
};
|
|
||||||
|
|
||||||
const commonInvalidateQueries = (query: QueryClient) => {
|
const commonInvalidateQueries = (query: QueryClient) => {
|
||||||
query.invalidateQueries(QUERY_KEY.BANK_RULES);
|
query.invalidateQueries(BANK_QUERY_KEY.BANK_RULES);
|
||||||
query.invalidateQueries(QUERY_KEY.RECOGNIZED_BANK_TRANSACTIONS_INFINITY);
|
query.invalidateQueries(BANK_QUERY_KEY.RECOGNIZED_BANK_TRANSACTIONS_INFINITY);
|
||||||
};
|
};
|
||||||
|
|
||||||
interface CreateBankRuleValues {
|
interface CreateBankRuleValues {
|
||||||
@@ -185,7 +176,7 @@ export function useDeleteBankRule(
|
|||||||
commonInvalidateQueries(queryClient);
|
commonInvalidateQueries(queryClient);
|
||||||
|
|
||||||
queryClient.invalidateQueries(
|
queryClient.invalidateQueries(
|
||||||
QUERY_KEY.RECOGNIZED_BANK_TRANSACTIONS_INFINITY,
|
BANK_QUERY_KEY.RECOGNIZED_BANK_TRANSACTIONS_INFINITY,
|
||||||
);
|
);
|
||||||
queryClient.invalidateQueries([
|
queryClient.invalidateQueries([
|
||||||
t.CASHFLOW_ACCOUNT_UNCATEGORIZED_TRANSACTIONS_INFINITY,
|
t.CASHFLOW_ACCOUNT_UNCATEGORIZED_TRANSACTIONS_INFINITY,
|
||||||
@@ -209,7 +200,7 @@ export function useBankRules(
|
|||||||
const apiRequest = useApiRequest();
|
const apiRequest = useApiRequest();
|
||||||
|
|
||||||
return useQuery<BankRulesResponse, Error>(
|
return useQuery<BankRulesResponse, Error>(
|
||||||
[QUERY_KEY.BANK_RULES],
|
[BANK_QUERY_KEY.BANK_RULES],
|
||||||
() => apiRequest.get('/banking/rules').then((res) => res.data.bank_rules),
|
() => apiRequest.get('/banking/rules').then((res) => res.data.bank_rules),
|
||||||
{ ...options },
|
{ ...options },
|
||||||
);
|
);
|
||||||
@@ -230,7 +221,7 @@ export function useBankRule(
|
|||||||
const apiRequest = useApiRequest();
|
const apiRequest = useApiRequest();
|
||||||
|
|
||||||
return useQuery<GetBankRuleRes, Error>(
|
return useQuery<GetBankRuleRes, Error>(
|
||||||
[QUERY_KEY.BANK_RULES, bankRuleId],
|
[BANK_QUERY_KEY.BANK_RULES, bankRuleId],
|
||||||
() =>
|
() =>
|
||||||
apiRequest
|
apiRequest
|
||||||
.get(`/banking/rules/${bankRuleId}`)
|
.get(`/banking/rules/${bankRuleId}`)
|
||||||
@@ -260,7 +251,7 @@ export function useGetBankTransactionsMatches(
|
|||||||
const apiRequest = useApiRequest();
|
const apiRequest = useApiRequest();
|
||||||
|
|
||||||
return useQuery<GetBankTransactionsMatchesResponse, Error>(
|
return useQuery<GetBankTransactionsMatchesResponse, Error>(
|
||||||
[QUERY_KEY.BANK_TRANSACTION_MATCHES, uncategorizeTransactionsIds],
|
[BANK_QUERY_KEY.BANK_TRANSACTION_MATCHES, uncategorizeTransactionsIds],
|
||||||
() =>
|
() =>
|
||||||
apiRequest
|
apiRequest
|
||||||
.get(`/cashflow/transactions/matches`, {
|
.get(`/cashflow/transactions/matches`, {
|
||||||
@@ -273,7 +264,9 @@ export function useGetBankTransactionsMatches(
|
|||||||
|
|
||||||
const onValidateExcludeUncategorizedTransaction = (queryClient) => {
|
const onValidateExcludeUncategorizedTransaction = (queryClient) => {
|
||||||
// Invalidate queries.
|
// Invalidate queries.
|
||||||
queryClient.invalidateQueries(QUERY_KEY.EXCLUDED_BANK_TRANSACTIONS_INFINITY);
|
queryClient.invalidateQueries(
|
||||||
|
BANK_QUERY_KEY.EXCLUDED_BANK_TRANSACTIONS_INFINITY,
|
||||||
|
);
|
||||||
queryClient.invalidateQueries(
|
queryClient.invalidateQueries(
|
||||||
t.CASHFLOW_ACCOUNT_UNCATEGORIZED_TRANSACTIONS_INFINITY,
|
t.CASHFLOW_ACCOUNT_UNCATEGORIZED_TRANSACTIONS_INFINITY,
|
||||||
);
|
);
|
||||||
@@ -282,7 +275,7 @@ const onValidateExcludeUncategorizedTransaction = (queryClient) => {
|
|||||||
queryClient.invalidateQueries(t.ACCOUNT);
|
queryClient.invalidateQueries(t.ACCOUNT);
|
||||||
|
|
||||||
// invalidate bank account summary.
|
// invalidate bank account summary.
|
||||||
queryClient.invalidateQueries(QUERY_KEY.BANK_ACCOUNT_SUMMARY_META);
|
queryClient.invalidateQueries(BANK_QUERY_KEY.BANK_ACCOUNT_SUMMARY_META);
|
||||||
};
|
};
|
||||||
|
|
||||||
type ExcludeUncategorizedTransactionValue = number;
|
type ExcludeUncategorizedTransactionValue = number;
|
||||||
@@ -319,6 +312,10 @@ export function useExcludeUncategorizedTransaction(
|
|||||||
{
|
{
|
||||||
onSuccess: (res, id) => {
|
onSuccess: (res, id) => {
|
||||||
onValidateExcludeUncategorizedTransaction(queryClient);
|
onValidateExcludeUncategorizedTransaction(queryClient);
|
||||||
|
queryClient.invalidateQueries([
|
||||||
|
BANK_QUERY_KEY.BANK_ACCOUNT_SUMMARY_META,
|
||||||
|
id,
|
||||||
|
]);
|
||||||
},
|
},
|
||||||
...options,
|
...options,
|
||||||
},
|
},
|
||||||
@@ -360,6 +357,10 @@ export function useUnexcludeUncategorizedTransaction(
|
|||||||
{
|
{
|
||||||
onSuccess: (res, id) => {
|
onSuccess: (res, id) => {
|
||||||
onValidateExcludeUncategorizedTransaction(queryClient);
|
onValidateExcludeUncategorizedTransaction(queryClient);
|
||||||
|
queryClient.invalidateQueries([
|
||||||
|
BANK_QUERY_KEY.BANK_ACCOUNT_SUMMARY_META,
|
||||||
|
id,
|
||||||
|
]);
|
||||||
},
|
},
|
||||||
...options,
|
...options,
|
||||||
},
|
},
|
||||||
@@ -483,7 +484,7 @@ export function useMatchUncategorizedTransaction(
|
|||||||
queryClient.invalidateQueries(t.ACCOUNT);
|
queryClient.invalidateQueries(t.ACCOUNT);
|
||||||
|
|
||||||
// Invalidate bank account summary.
|
// Invalidate bank account summary.
|
||||||
queryClient.invalidateQueries(QUERY_KEY.BANK_ACCOUNT_SUMMARY_META);
|
queryClient.invalidateQueries(BANK_QUERY_KEY.BANK_ACCOUNT_SUMMARY_META);
|
||||||
},
|
},
|
||||||
...props,
|
...props,
|
||||||
});
|
});
|
||||||
@@ -529,7 +530,7 @@ export function useUnmatchMatchedUncategorizedTransaction(
|
|||||||
queryClient.invalidateQueries(t.ACCOUNT);
|
queryClient.invalidateQueries(t.ACCOUNT);
|
||||||
|
|
||||||
// Invalidate bank account summary.
|
// Invalidate bank account summary.
|
||||||
queryClient.invalidateQueries(QUERY_KEY.BANK_ACCOUNT_SUMMARY_META);
|
queryClient.invalidateQueries(BANK_QUERY_KEY.BANK_ACCOUNT_SUMMARY_META);
|
||||||
},
|
},
|
||||||
...props,
|
...props,
|
||||||
});
|
});
|
||||||
@@ -550,7 +551,7 @@ export function useGetRecognizedBankTransaction(
|
|||||||
const apiRequest = useApiRequest();
|
const apiRequest = useApiRequest();
|
||||||
|
|
||||||
return useQuery<GetRecognizedBankTransactionRes, Error>(
|
return useQuery<GetRecognizedBankTransactionRes, Error>(
|
||||||
[QUERY_KEY.RECOGNIZED_BANK_TRANSACTION, uncategorizedTransactionId],
|
[BANK_QUERY_KEY.RECOGNIZED_BANK_TRANSACTION, uncategorizedTransactionId],
|
||||||
() =>
|
() =>
|
||||||
apiRequest
|
apiRequest
|
||||||
.get(`/banking/recognized/transactions/${uncategorizedTransactionId}`)
|
.get(`/banking/recognized/transactions/${uncategorizedTransactionId}`)
|
||||||
@@ -578,7 +579,7 @@ export function useGetBankAccountSummaryMeta(
|
|||||||
const apiRequest = useApiRequest();
|
const apiRequest = useApiRequest();
|
||||||
|
|
||||||
return useQuery<GetBankAccountSummaryMetaRes, Error>(
|
return useQuery<GetBankAccountSummaryMetaRes, Error>(
|
||||||
[QUERY_KEY.BANK_ACCOUNT_SUMMARY_META, bankAccountId],
|
[BANK_QUERY_KEY.BANK_ACCOUNT_SUMMARY_META, bankAccountId],
|
||||||
() =>
|
() =>
|
||||||
apiRequest
|
apiRequest
|
||||||
.get(`/banking/bank_accounts/${bankAccountId}/meta`)
|
.get(`/banking/bank_accounts/${bankAccountId}/meta`)
|
||||||
@@ -610,7 +611,7 @@ export function useGetAutofillCategorizeTransaction(
|
|||||||
|
|
||||||
return useQuery<GetAutofillCategorizeTransaction, Error>(
|
return useQuery<GetAutofillCategorizeTransaction, Error>(
|
||||||
[
|
[
|
||||||
QUERY_KEY.AUTOFILL_CATEGORIZE_BANK_TRANSACTION,
|
BANK_QUERY_KEY.AUTOFILL_CATEGORIZE_BANK_TRANSACTION,
|
||||||
uncategorizedTransactionIds,
|
uncategorizedTransactionIds,
|
||||||
],
|
],
|
||||||
() =>
|
() =>
|
||||||
@@ -634,7 +635,7 @@ export function useRecognizedBankTransactionsInfinity(
|
|||||||
const apiRequest = useApiRequest();
|
const apiRequest = useApiRequest();
|
||||||
|
|
||||||
return useInfiniteQuery(
|
return useInfiniteQuery(
|
||||||
[QUERY_KEY.RECOGNIZED_BANK_TRANSACTIONS_INFINITY, query],
|
[BANK_QUERY_KEY.RECOGNIZED_BANK_TRANSACTIONS_INFINITY, query],
|
||||||
async ({ pageParam = 1 }) => {
|
async ({ pageParam = 1 }) => {
|
||||||
const response = await apiRequest.http({
|
const response = await apiRequest.http({
|
||||||
...axios,
|
...axios,
|
||||||
@@ -666,7 +667,7 @@ export function useExcludedBankTransactionsInfinity(
|
|||||||
const apiRequest = useApiRequest();
|
const apiRequest = useApiRequest();
|
||||||
|
|
||||||
return useInfiniteQuery(
|
return useInfiniteQuery(
|
||||||
[QUERY_KEY.EXCLUDED_BANK_TRANSACTIONS_INFINITY, query],
|
[BANK_QUERY_KEY.EXCLUDED_BANK_TRANSACTIONS_INFINITY, query],
|
||||||
async ({ pageParam = 1 }) => {
|
async ({ pageParam = 1 }) => {
|
||||||
const response = await apiRequest.http({
|
const response = await apiRequest.http({
|
||||||
...axios,
|
...axios,
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import useApiRequest from '../useRequest';
|
|||||||
import { transformToCamelCase } from '@/utils';
|
import { transformToCamelCase } from '@/utils';
|
||||||
import { downloadFile, useDownloadFile } from '../useDownloadFile';
|
import { downloadFile, useDownloadFile } from '../useDownloadFile';
|
||||||
import T from './types';
|
import T from './types';
|
||||||
|
import { BANK_QUERY_KEY } from '@/constants/query-keys/banking';
|
||||||
|
|
||||||
const QueryKeys = {
|
const QueryKeys = {
|
||||||
ImportPreview: 'ImportPreview',
|
ImportPreview: 'ImportPreview',
|
||||||
@@ -215,6 +216,7 @@ const invalidateResourcesOnImport = (
|
|||||||
T.CASHFLOW_ACCOUNT_UNCATEGORIZED_TRANSACTIONS_INFINITY,
|
T.CASHFLOW_ACCOUNT_UNCATEGORIZED_TRANSACTIONS_INFINITY,
|
||||||
);
|
);
|
||||||
queryClient.invalidateQueries(T.CASHFLOW_UNCAATEGORIZED_TRANSACTION);
|
queryClient.invalidateQueries(T.CASHFLOW_UNCAATEGORIZED_TRANSACTION);
|
||||||
|
queryClient.invalidateQueries(BANK_QUERY_KEY.BANK_ACCOUNT_SUMMARY_META);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user