fix: validate exclude and unexclude uncategorized transaction

This commit is contained in:
Ahmed Bouhuolia
2024-08-05 15:56:11 +02:00
parent 6d0d0689e1
commit 8e99a31455
8 changed files with 68 additions and 10 deletions

View File

@@ -20,6 +20,7 @@ export default class UncategorizedCashflowTransaction extends mixin(
description!: string;
plaidTransactionId!: string;
recognizedTransactionId!: number;
excludedAt: Date;
/**
* Table name.
@@ -45,6 +46,7 @@ export default class UncategorizedCashflowTransaction extends mixin(
'isDepositTransaction',
'isWithdrawalTransaction',
'isRecognized',
'isExcluded'
];
}
@@ -89,6 +91,14 @@ export default class UncategorizedCashflowTransaction extends mixin(
return !!this.recognizedTransactionId;
}
/**
* Detarmines whether the transaction is excluded.
* @returns {boolean}
*/
public get isExcluded(): boolean {
return !!this.excludedAt;
}
/**
* Model modifiers.
*/

View File

@@ -1,7 +1,11 @@
import { Knex } from 'knex';
import { Inject, Service } from 'typedi';
import HasTenancyService from '@/services/Tenancy/TenancyService';
import UnitOfWork from '@/services/UnitOfWork';
import { Inject, Service } from 'typedi';
import { validateTransactionNotCategorized } from './utils';
import {
validateTransactionNotCategorized,
validateTransactionNotExcluded,
} from './utils';
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
import events from '@/subscribers/events';
import {
@@ -37,9 +41,13 @@ export class ExcludeBankTransaction {
.findById(uncategorizedTransactionId)
.throwIfNotFound();
// Validate the transaction shouldn't be excluded.
validateTransactionNotExcluded(oldUncategorizedTransaction);
// Validate the transaction shouldn't be categorized.
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, {
tenantId,
uncategorizedTransactionId,

View File

@@ -1,6 +1,6 @@
import { Inject, Service } from 'typedi';
import PromisePool from '@supercharge/promise-pool';
import { castArray } from 'lodash';
import { castArray, uniq } from 'lodash';
import { ExcludeBankTransaction } from './ExcludeBankTransaction';
@Service()
@@ -18,7 +18,7 @@ export class ExcludeBankTransactions {
tenantId: number,
bankTransactionIds: Array<number> | number
) {
const _bankTransactionIds = castArray(bankTransactionIds);
const _bankTransactionIds = uniq(castArray(bankTransactionIds));
await PromisePool.withConcurrency(1)
.for(_bankTransactionIds)

View File

@@ -1,7 +1,11 @@
import { Knex } from 'knex';
import { Inject, Service } from 'typedi';
import HasTenancyService from '@/services/Tenancy/TenancyService';
import UnitOfWork from '@/services/UnitOfWork';
import { Inject, Service } from 'typedi';
import { validateTransactionNotCategorized } from './utils';
import {
validateTransactionNotCategorized,
validateTransactionShouldBeExcluded,
} from './utils';
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
import events from '@/subscribers/events';
import {
@@ -37,9 +41,13 @@ export class UnexcludeBankTransaction {
.findById(uncategorizedTransactionId)
.throwIfNotFound();
// Validate the transaction should be excludded.
validateTransactionShouldBeExcluded(oldUncategorizedTransaction);
// Validate the transaction shouldn't be categorized.
validateTransactionNotCategorized(oldUncategorizedTransaction);
return this.uow.withTransaction(tenantId, async (trx) => {
return this.uow.withTransaction(tenantId, async (trx: Knex.Transaction) => {
await this.eventPublisher.emitAsync(
events.bankTransactions.onUnexcluding,
{

View File

@@ -1,7 +1,7 @@
import { Inject, Service } from 'typedi';
import PromisePool from '@supercharge/promise-pool';
import { UnexcludeBankTransaction } from './UnexcludeBankTransaction';
import { castArray } from 'lodash';
import { castArray, uniq } from 'lodash';
@Service()
export class UnexcludeBankTransactions {
@@ -17,7 +17,7 @@ export class UnexcludeBankTransactions {
tenantId: number,
bankTransactionIds: Array<number> | number
) {
const _bankTransactionIds = castArray(bankTransactionIds);
const _bankTransactionIds = uniq(castArray(bankTransactionIds));
await PromisePool.withConcurrency(1)
.for(_bankTransactionIds)

View File

@@ -3,6 +3,8 @@ import UncategorizedCashflowTransaction from '@/models/UncategorizedCashflowTran
const ERRORS = {
TRANSACTION_ALREADY_CATEGORIZED: 'TRANSACTION_ALREADY_CATEGORIZED',
TRANSACTION_ALREADY_EXCLUDED: 'TRANSACTION_ALREADY_EXCLUDED',
TRANSACTION_NOT_EXCLUDED: 'TRANSACTION_NOT_EXCLUDED',
};
export const validateTransactionNotCategorized = (
@@ -12,3 +14,19 @@ export const validateTransactionNotCategorized = (
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);
}
};

View File

@@ -71,6 +71,11 @@ function AccountTransactionsDataTable({
const handleCategorizeBtnClick = (transaction) => {
setUncategorizedTransactionIdForMatching(transaction.id);
};
// handles table selected rows change.
const handleSelectedRowsChange = (selected) => {
const transactionIds = selected.map((r) => r.original.id);
setUncategorizedTransactionsSelected(transactionIds);
};
// Handle exclude transaction.
const handleExcludeTransaction = (transaction) => {
excludeTransaction(transaction.id)
@@ -118,6 +123,7 @@ function AccountTransactionsDataTable({
onExclude: handleExcludeTransaction,
onCategorize: handleCategorizeBtnClick,
}}
onSelectedRowsChange={handleSelectedRowsChange}
className={clsx('table-constrant', styles.table, {
[styles.showCategorizeColumn]: enableMultipleCategorization,
})}

View File

@@ -319,6 +319,10 @@ export function useExcludeUncategorizedTransaction(
{
onSuccess: (res, id) => {
onValidateExcludeUncategorizedTransaction(queryClient);
queryClient.invalidateQueries([
QUERY_KEY.BANK_ACCOUNT_SUMMARY_META,
id,
]);
},
...options,
},
@@ -360,6 +364,10 @@ export function useUnexcludeUncategorizedTransaction(
{
onSuccess: (res, id) => {
onValidateExcludeUncategorizedTransaction(queryClient);
queryClient.invalidateQueries([
QUERY_KEY.BANK_ACCOUNT_SUMMARY_META,
id,
]);
},
...options,
},