mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-16 12:50:38 +00:00
fix: improvements to bank matching transactions
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
import { Server } from 'socket.io';
|
||||
import { Inject, Service } from 'typedi';
|
||||
import { initialize } from 'objection';
|
||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
|
||||
@Service()
|
||||
export class GetBankAccountSummary {
|
||||
@@ -14,22 +14,41 @@ export class GetBankAccountSummary {
|
||||
* @returns
|
||||
*/
|
||||
public async getBankAccountSummary(tenantId: number, bankAccountId: number) {
|
||||
const knex = this.tenancy.knex(tenantId);
|
||||
const {
|
||||
Account,
|
||||
UncategorizedCashflowTransaction,
|
||||
RecognizedBankTransaction,
|
||||
} = this.tenancy.models(tenantId);
|
||||
|
||||
await initialize(knex, [
|
||||
UncategorizedCashflowTransaction,
|
||||
RecognizedBankTransaction,
|
||||
]);
|
||||
const bankAccount = await Account.query()
|
||||
.findById(bankAccountId)
|
||||
.throwIfNotFound();
|
||||
|
||||
// Retrieves the uncategorized transactions count of the given bank account.
|
||||
const uncategorizedTranasctionsCount =
|
||||
await UncategorizedCashflowTransaction.query()
|
||||
.where('accountId', bankAccountId)
|
||||
.count('id as total')
|
||||
.first();
|
||||
await UncategorizedCashflowTransaction.query().onBuild((q) => {
|
||||
// Include just the given account.
|
||||
q.where('accountId', bankAccountId);
|
||||
|
||||
// Only the not excluded.
|
||||
q.modify('notExcluded');
|
||||
|
||||
// Only the not categorized.
|
||||
q.modify('notCategorized');
|
||||
|
||||
// Only the not matched bank transactions.
|
||||
q.withGraphJoined('matchedBankTransactions');
|
||||
q.whereNull('matchedBankTransactions.id');
|
||||
|
||||
// Count the results.
|
||||
q.count('uncategorized_cashflow_transactions.id as total');
|
||||
q.first();
|
||||
});
|
||||
|
||||
// Retrieves the recognized transactions count of the given bank account.
|
||||
const recognizedTransactionsCount = await RecognizedBankTransaction.query()
|
||||
@@ -43,8 +62,8 @@ export class GetBankAccountSummary {
|
||||
.first();
|
||||
|
||||
const totalUncategorizedTransactions =
|
||||
uncategorizedTranasctionsCount?.total;
|
||||
const totalRecognizedTransactions = recognizedTransactionsCount?.total;
|
||||
uncategorizedTranasctionsCount?.total || 0;
|
||||
const totalRecognizedTransactions = recognizedTransactionsCount?.total || 0;
|
||||
|
||||
return {
|
||||
name: bankAccount.name,
|
||||
|
||||
@@ -31,6 +31,7 @@ export class UnmatchMatchedBankTransaction {
|
||||
return this.uow.withTransaction(tenantId, async (trx) => {
|
||||
await this.eventPublisher.emitAsync(events.bankMatch.onUnmatching, {
|
||||
tenantId,
|
||||
uncategorizedTransactionId,
|
||||
trx,
|
||||
} as IBankTransactionUnmatchingEventPayload);
|
||||
|
||||
@@ -40,6 +41,7 @@ export class UnmatchMatchedBankTransaction {
|
||||
|
||||
await this.eventPublisher.emitAsync(events.bankMatch.onUnmatched, {
|
||||
tenantId,
|
||||
uncategorizedTransactionId,
|
||||
trx,
|
||||
} as IBankTransactionUnmatchingEventPayload);
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Knex } from 'knex';
|
||||
import { Inject, Service } from 'typedi';
|
||||
import { ServiceError } from '@/exceptions';
|
||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
import { Inject, Service } from 'typedi';
|
||||
import { ERRORS } from './types';
|
||||
|
||||
@Service()
|
||||
@@ -18,12 +19,13 @@ export class ValidateTransactionMatched {
|
||||
public async validateTransactionNoMatchLinking(
|
||||
tenantId: number,
|
||||
referenceType: string,
|
||||
referenceId: number
|
||||
referenceId: number,
|
||||
trx?: Knex.Transaction
|
||||
) {
|
||||
const { MatchedBankTransaction } = this.tenancy.models(tenantId);
|
||||
|
||||
const foundMatchedTransaction =
|
||||
await MatchedBankTransaction.query().findOne({
|
||||
await MatchedBankTransaction.query(trx).findOne({
|
||||
referenceType,
|
||||
referenceId,
|
||||
});
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
import { Inject, Service } from 'typedi';
|
||||
import events from '@/subscribers/events';
|
||||
import {
|
||||
IBankTransactionMatchedEventPayload,
|
||||
IBankTransactionUnmatchedEventPayload,
|
||||
} from '../types';
|
||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
|
||||
@Service()
|
||||
export class DecrementUncategorizedTransactionOnMatching {
|
||||
@Inject()
|
||||
private tenancy: HasTenancyService;
|
||||
/**
|
||||
* Constructor method.
|
||||
*/
|
||||
public attach(bus) {
|
||||
bus.subscribe(
|
||||
events.bankMatch.onMatched,
|
||||
this.decrementUnCategorizedTransactionsOnMatching.bind(this)
|
||||
);
|
||||
bus.subscribe(
|
||||
events.bankMatch.onUnmatched,
|
||||
this.incrementUnCategorizedTransactionsOnUnmatching.bind(this)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the cashflow transaction whether matched with bank transaction on deleting.
|
||||
* @param {IManualJournalDeletingPayload}
|
||||
*/
|
||||
public async decrementUnCategorizedTransactionsOnMatching({
|
||||
tenantId,
|
||||
uncategorizedTransactionId,
|
||||
matchTransactionsDTO,
|
||||
trx,
|
||||
}: IBankTransactionMatchedEventPayload) {
|
||||
const { UncategorizedCashflowTransaction, Account } =
|
||||
this.tenancy.models(tenantId);
|
||||
|
||||
const transaction = await UncategorizedCashflowTransaction.query().findById(
|
||||
uncategorizedTransactionId
|
||||
);
|
||||
//
|
||||
await Account.query(trx)
|
||||
.findById(transaction.accountId)
|
||||
.decrement('uncategorizedTransactions', 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the cashflow transaction whether matched with bank transaction on deleting.
|
||||
* @param {IManualJournalDeletingPayload}
|
||||
*/
|
||||
public async incrementUnCategorizedTransactionsOnUnmatching({
|
||||
tenantId,
|
||||
uncategorizedTransactionId,
|
||||
trx,
|
||||
}: IBankTransactionUnmatchedEventPayload) {
|
||||
const { UncategorizedCashflowTransaction, Account } =
|
||||
this.tenancy.models(tenantId);
|
||||
|
||||
const transaction = await UncategorizedCashflowTransaction.query().findById(
|
||||
uncategorizedTransactionId
|
||||
);
|
||||
//
|
||||
await Account.query(trx)
|
||||
.findById(transaction.accountId)
|
||||
.decrement('uncategorizedTransactions', 1);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Inject, Service } from 'typedi';
|
||||
import { IManualJournalDeletingPayload } from '@/interfaces';
|
||||
import { ICommandCashflowDeletingPayload, IManualJournalDeletingPayload } from '@/interfaces';
|
||||
import events from '@/subscribers/events';
|
||||
import { ValidateTransactionMatched } from '../ValidateTransactionsMatched';
|
||||
|
||||
@@ -24,13 +24,14 @@ export class ValidateMatchingOnCashflowDelete {
|
||||
*/
|
||||
public async validateMatchingOnCashflowDeleting({
|
||||
tenantId,
|
||||
oldManualJournal,
|
||||
oldCashflowTransaction,
|
||||
trx,
|
||||
}: IManualJournalDeletingPayload) {
|
||||
}: ICommandCashflowDeletingPayload) {
|
||||
await this.validateNoMatchingLinkedService.validateTransactionNoMatchLinking(
|
||||
tenantId,
|
||||
'ManualJournal',
|
||||
oldManualJournal.id
|
||||
'CashflowTransaction',
|
||||
oldCashflowTransaction.id,
|
||||
trx
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,8 @@ export class ValidateMatchingOnExpenseDelete {
|
||||
await this.validateNoMatchingLinkedService.validateTransactionNoMatchLinking(
|
||||
tenantId,
|
||||
'Expense',
|
||||
oldExpense.id
|
||||
oldExpense.id,
|
||||
trx
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,8 @@ export class ValidateMatchingOnManualJournalDelete {
|
||||
await this.validateNoMatchingLinkedService.validateTransactionNoMatchLinking(
|
||||
tenantId,
|
||||
'ManualJournal',
|
||||
oldManualJournal.id
|
||||
oldManualJournal.id,
|
||||
trx
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,8 @@ export class ValidateMatchingOnPaymentMadeDelete {
|
||||
await this.validateNoMatchingLinkedService.validateTransactionNoMatchLinking(
|
||||
tenantId,
|
||||
'PaymentMade',
|
||||
oldBillPayment.id
|
||||
oldBillPayment.id,
|
||||
trx
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,8 @@ export class ValidateMatchingOnPaymentReceivedDelete {
|
||||
await this.validateNoMatchingLinkedService.validateTransactionNoMatchLinking(
|
||||
tenantId,
|
||||
'PaymentReceive',
|
||||
oldPaymentReceive.id
|
||||
oldPaymentReceive.id,
|
||||
trx
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,14 @@ export interface IBankTransactionMatchedEventPayload {
|
||||
|
||||
export interface IBankTransactionUnmatchingEventPayload {
|
||||
tenantId: number;
|
||||
uncategorizedTransactionId: number;
|
||||
trx?: Knex.Transaction;
|
||||
}
|
||||
|
||||
export interface IBankTransactionUnmatchedEventPayload {
|
||||
tenantId: number;
|
||||
uncategorizedTransactionId: number;
|
||||
trx?: Knex.Transaction;
|
||||
}
|
||||
|
||||
export interface IMatchTransactionDTO {
|
||||
|
||||
Reference in New Issue
Block a user