mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-20 06:40:31 +00:00
fix: validate exclude and unexclude uncategorized transaction
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,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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
@@ -71,6 +71,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 +123,7 @@ function AccountTransactionsDataTable({
|
|||||||
onExclude: handleExcludeTransaction,
|
onExclude: handleExcludeTransaction,
|
||||||
onCategorize: handleCategorizeBtnClick,
|
onCategorize: handleCategorizeBtnClick,
|
||||||
}}
|
}}
|
||||||
|
onSelectedRowsChange={handleSelectedRowsChange}
|
||||||
className={clsx('table-constrant', styles.table, {
|
className={clsx('table-constrant', styles.table, {
|
||||||
[styles.showCategorizeColumn]: enableMultipleCategorization,
|
[styles.showCategorizeColumn]: enableMultipleCategorization,
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -319,6 +319,10 @@ export function useExcludeUncategorizedTransaction(
|
|||||||
{
|
{
|
||||||
onSuccess: (res, id) => {
|
onSuccess: (res, id) => {
|
||||||
onValidateExcludeUncategorizedTransaction(queryClient);
|
onValidateExcludeUncategorizedTransaction(queryClient);
|
||||||
|
queryClient.invalidateQueries([
|
||||||
|
QUERY_KEY.BANK_ACCOUNT_SUMMARY_META,
|
||||||
|
id,
|
||||||
|
]);
|
||||||
},
|
},
|
||||||
...options,
|
...options,
|
||||||
},
|
},
|
||||||
@@ -360,6 +364,10 @@ export function useUnexcludeUncategorizedTransaction(
|
|||||||
{
|
{
|
||||||
onSuccess: (res, id) => {
|
onSuccess: (res, id) => {
|
||||||
onValidateExcludeUncategorizedTransaction(queryClient);
|
onValidateExcludeUncategorizedTransaction(queryClient);
|
||||||
|
queryClient.invalidateQueries([
|
||||||
|
QUERY_KEY.BANK_ACCOUNT_SUMMARY_META,
|
||||||
|
id,
|
||||||
|
]);
|
||||||
},
|
},
|
||||||
...options,
|
...options,
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user