fix: avoid decrement/increment for pending bank transactions

This commit is contained in:
Ahmed Bouhuolia
2024-08-12 10:48:36 +02:00
parent 7054e862d5
commit cb016be78c
6 changed files with 57 additions and 5 deletions

View File

@@ -285,3 +285,17 @@ export interface IUncategorizedTransactionCreatedEventPayload {
createUncategorizedTransactionDTO: CreateUncategorizedTransactionDTO; createUncategorizedTransactionDTO: CreateUncategorizedTransactionDTO;
trx: Knex.Transaction; trx: Knex.Transaction;
} }
export interface IPendingTransactionRemovingEventPayload {
tenantId: number;
uncategorizedTransactionId: number;
pendingTransaction: IUncategorizedCashflowTransaction;
trx?: Knex.Transaction;
}
export interface IPendingTransactionRemovedEventPayload {
tenantId: number;
uncategorizedTransactionId: number;
pendingTransaction: IUncategorizedCashflowTransaction;
trx?: Knex.Transaction;
}

View File

@@ -52,6 +52,9 @@ export class GetBankAccountSummary {
q.withGraphJoined('matchedBankTransactions'); q.withGraphJoined('matchedBankTransactions');
q.whereNull('matchedBankTransactions.id'); q.whereNull('matchedBankTransactions.id');
// Exclude the pending transactions.
q.modify('notPending');
// Count the results. // Count the results.
q.count('uncategorized_cashflow_transactions.id as total'); q.count('uncategorized_cashflow_transactions.id as total');
q.first(); q.first();
@@ -65,6 +68,9 @@ export class GetBankAccountSummary {
q.withGraphJoined('recognizedTransaction'); q.withGraphJoined('recognizedTransaction');
q.whereNotNull('recognizedTransaction.id'); q.whereNotNull('recognizedTransaction.id');
// Exclude the pending transactions.
q.modify('notPending');
// Count the results. // Count the results.
q.count('uncategorized_cashflow_transactions.id as total'); q.count('uncategorized_cashflow_transactions.id as total');
q.first(); q.first();
@@ -75,6 +81,9 @@ export class GetBankAccountSummary {
q.where('accountId', bankAccountId); q.where('accountId', bankAccountId);
q.modify('excluded'); q.modify('excluded');
// Exclude the pending transactions.
q.modify('notPending');
// Count the results. // Count the results.
q.count('uncategorized_cashflow_transactions.id as total'); q.count('uncategorized_cashflow_transactions.id as total');
q.first(); q.first();

View File

@@ -34,7 +34,9 @@ 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'); q.modify('notExcluded');
q.modify('notPending');
if (_filter.accountId) { if (_filter.accountId) {
q.where('accountId', _filter.accountId); q.where('accountId', _filter.accountId);

View File

@@ -51,7 +51,9 @@ export class GetUncategorizedTransactions {
.onBuild((q) => { .onBuild((q) => {
q.where('accountId', accountId); q.where('accountId', accountId);
q.where('categorized', false); q.where('categorized', false);
q.modify('notExcluded'); q.modify('notExcluded');
q.modify('notPending');
q.withGraphFetched('account'); q.withGraphFetched('account');
q.withGraphFetched('recognizedTransaction.assignAccount'); q.withGraphFetched('recognizedTransaction.assignAccount');

View File

@@ -6,6 +6,10 @@ import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
import events from '@/subscribers/events'; import events from '@/subscribers/events';
import { ServiceError } from '@/exceptions'; import { ServiceError } from '@/exceptions';
import { ERRORS } from './constants'; import { ERRORS } from './constants';
import {
IPendingTransactionRemovedEventPayload,
IPendingTransactionRemovingEventPayload,
} from '@/interfaces';
@Service() @Service()
export class RemovePendingUncategorizedTransaction { export class RemovePendingUncategorizedTransaction {
@@ -42,7 +46,12 @@ export class RemovePendingUncategorizedTransaction {
return this.uow.withTransaction(tenantId, async (trx: Knex.Transaction) => { return this.uow.withTransaction(tenantId, async (trx: Knex.Transaction) => {
await this.eventPublisher.emitAsync( await this.eventPublisher.emitAsync(
events.bankTransactions.onPendingRemoving, events.bankTransactions.onPendingRemoving,
{ tenantId, uncategorizedTransactionId, trx } {
tenantId,
uncategorizedTransactionId,
pendingTransaction,
trx,
} as IPendingTransactionRemovingEventPayload
); );
// Removes the pending uncategorized transaction. // Removes the pending uncategorized transaction.
await UncategorizedCashflowTransaction.query(trx) await UncategorizedCashflowTransaction.query(trx)
@@ -51,7 +60,12 @@ export class RemovePendingUncategorizedTransaction {
await this.eventPublisher.emitAsync( await this.eventPublisher.emitAsync(
events.bankTransactions.onPendingRemoved, events.bankTransactions.onPendingRemoved,
{ tenantId, uncategorizedTransactionId, trx } {
tenantId,
uncategorizedTransactionId,
pendingTransaction,
trx,
} as IPendingTransactionRemovedEventPayload
); );
}); });
} }

View File

@@ -1,11 +1,11 @@
import { Inject, Service } from 'typedi'; import { Inject, Service } from 'typedi';
import PromisePool from '@supercharge/promise-pool';
import events from '@/subscribers/events'; import events from '@/subscribers/events';
import HasTenancyService from '@/services/Tenancy/TenancyService'; import HasTenancyService from '@/services/Tenancy/TenancyService';
import { import {
ICashflowTransactionCategorizedPayload, ICashflowTransactionCategorizedPayload,
ICashflowTransactionUncategorizedPayload, ICashflowTransactionUncategorizedPayload,
} from '@/interfaces'; } from '@/interfaces';
import PromisePool from '@supercharge/promise-pool';
@Service() @Service()
export class DecrementUncategorizedTransactionOnCategorize { export class DecrementUncategorizedTransactionOnCategorize {
@@ -36,13 +36,17 @@ export class DecrementUncategorizedTransactionOnCategorize {
public async decrementUnCategorizedTransactionsOnCategorized({ public async decrementUnCategorizedTransactionsOnCategorized({
tenantId, tenantId,
uncategorizedTransactions, uncategorizedTransactions,
trx trx,
}: ICashflowTransactionCategorizedPayload) { }: ICashflowTransactionCategorizedPayload) {
const { Account } = this.tenancy.models(tenantId); const { Account } = this.tenancy.models(tenantId);
await PromisePool.withConcurrency(1) await PromisePool.withConcurrency(1)
.for(uncategorizedTransactions) .for(uncategorizedTransactions)
.process(async (uncategorizedTransaction) => { .process(async (uncategorizedTransaction) => {
// Cannot continue if the transaction is still pending.
if (uncategorizedTransaction.isPending) {
return;
}
await Account.query(trx) await Account.query(trx)
.findById(uncategorizedTransaction.accountId) .findById(uncategorizedTransaction.accountId)
.decrement('uncategorizedTransactions', 1); .decrement('uncategorizedTransactions', 1);
@@ -56,13 +60,17 @@ export class DecrementUncategorizedTransactionOnCategorize {
public async incrementUnCategorizedTransactionsOnUncategorized({ public async incrementUnCategorizedTransactionsOnUncategorized({
tenantId, tenantId,
uncategorizedTransactions, uncategorizedTransactions,
trx trx,
}: ICashflowTransactionUncategorizedPayload) { }: ICashflowTransactionUncategorizedPayload) {
const { Account } = this.tenancy.models(tenantId); const { Account } = this.tenancy.models(tenantId);
await PromisePool.withConcurrency(1) await PromisePool.withConcurrency(1)
.for(uncategorizedTransactions) .for(uncategorizedTransactions)
.process(async (uncategorizedTransaction) => { .process(async (uncategorizedTransaction) => {
// Cannot continue if the transaction is still pending.
if (uncategorizedTransaction.isPending) {
return;
}
await Account.query(trx) await Account.query(trx)
.findById(uncategorizedTransaction.accountId) .findById(uncategorizedTransaction.accountId)
.increment('uncategorizedTransactions', 1); .increment('uncategorizedTransactions', 1);
@@ -82,6 +90,9 @@ export class DecrementUncategorizedTransactionOnCategorize {
if (!uncategorizedTransaction.accountId) return; if (!uncategorizedTransaction.accountId) return;
// Cannot continue if the transaction is still pending.
if (uncategorizedTransaction.isPending) return;
await Account.query(trx) await Account.query(trx)
.findById(uncategorizedTransaction.accountId) .findById(uncategorizedTransaction.accountId)
.increment('uncategorizedTransactions', 1); .increment('uncategorizedTransactions', 1);