Skip to content

Commit

Permalink
Merge pull request #523 from bigcapitalhq/matching-transactions-fixes
Browse files Browse the repository at this point in the history
fix: Matching transactions bugs
  • Loading branch information
abouolia authored Jul 8, 2024
2 parents aa89653 + 73acdb6 commit d096e49
Show file tree
Hide file tree
Showing 32 changed files with 389 additions and 133 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ exports.up = function (knex) {
.integer('uncategorized_transaction_id')
.unsigned()
.references('id')
.inTable('uncategorized_cashflow_transactions');
.inTable('uncategorized_cashflow_transactions')
.withKeyName('recognizedBankTransactionsUncategorizedTransIdForeign');
table
.integer('bank_rule_id')
.unsigned()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
exports.up = function (knex) {
return knex.schema.table('uncategorized_cashflow_transactions', (table) => {
table.integer('recognized_transaction_id').unsigned();
table
.integer('recognized_transaction_id')
.unsigned()
.references('id')
.inTable('recognized_bank_transactions')
.withKeyName('uncategorizedCashflowTransRecognizedTranIdForeign');
});
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
exports.up = function (knex) {
return knex.schema.createTable('matched_bank_transactions', (table) => {
table.increments('id');
table.integer('uncategorized_transaction_id').unsigned();
table
.integer('uncategorized_transaction_id')
.unsigned()
.references('id')
.inTable('uncategorized_cashflow_transactions');
table.string('reference_type');
table.integer('reference_id').unsigned();
table.decimal('amount');
Expand Down
3 changes: 2 additions & 1 deletion packages/server/src/interfaces/CashflowService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,9 @@ export interface ICommandCashflowDeletedPayload {

export interface ICashflowTransactionCategorizedPayload {
tenantId: number;
cashflowTransactionId: number;
uncategorizedTransaction: any;
cashflowTransaction: ICashflowTransaction;
categorizeDTO: any;
trx: Knex.Transaction;
}
export interface ICashflowTransactionUncategorizingPayload {
Expand Down
8 changes: 8 additions & 0 deletions packages/server/src/interfaces/Import.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { ImportFilePreviewPOJO } from "@/services/Import/interfaces";


export interface IImportFileCommitedEventPayload {
tenantId: number;
importId: number;
meta: ImportFilePreviewPOJO;
}
2 changes: 2 additions & 0 deletions packages/server/src/loaders/eventEmitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ import { RecognizeSyncedBankTranasctions } from '@/services/Banking/Plaid/subscr
import { UnlinkBankRuleOnDeleteBankRule } from '@/services/Banking/Rules/events/UnlinkBankRuleOnDeleteBankRule';
import { DecrementUncategorizedTransactionOnMatching } from '@/services/Banking/Matching/events/DecrementUncategorizedTransactionsOnMatch';
import { DecrementUncategorizedTransactionOnExclude } from '@/services/Banking/Exclude/events/DecrementUncategorizedTransactionOnExclude';
import { DecrementUncategorizedTransactionOnCategorize } from '@/services/Cashflow/subscribers/DecrementUncategorizedTransactionOnCategorize';

export default () => {
return new EventPublisher();
Expand Down Expand Up @@ -262,6 +263,7 @@ export const susbcribers = () => {
UnlinkBankRuleOnDeleteBankRule,
DecrementUncategorizedTransactionOnMatching,
DecrementUncategorizedTransactionOnExclude,
DecrementUncategorizedTransactionOnCategorize,

// Validate matching
ValidateMatchingOnCashflowDelete,
Expand Down
52 changes: 0 additions & 52 deletions packages/server/src/models/UncategorizedCashflowTransaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,56 +184,4 @@ export default class UncategorizedCashflowTransaction extends mixin(
},
};
}

/**
* Updates the count of uncategorized transactions for the associated account
* based on the specified operation.
* @param {QueryContext} queryContext - The query context for the transaction.
* @param {boolean} increment - Indicates whether to increment or decrement the count.
*/
private async updateUncategorizedTransactionCount(
queryContext: QueryContext,
increment: boolean,
amount: number = 1
) {
const operation = increment ? 'increment' : 'decrement';

await Account.query(queryContext.transaction)
.findById(this.accountId)
[operation]('uncategorized_transactions', amount);
}

/**
* Runs after insert.
* @param {QueryContext} queryContext
*/
public async $afterInsert(queryContext) {
await super.$afterInsert(queryContext);
await this.updateUncategorizedTransactionCount(queryContext, true);
}

/**
* Runs after update.
* @param {ModelOptions} opt
* @param {QueryContext} queryContext
*/
public async $afterUpdate(
opt: ModelOptions,
queryContext: QueryContext
): Promise<any> {
await super.$afterUpdate(opt, queryContext);

if (this.id && this.categorized) {
await this.updateUncategorizedTransactionCount(queryContext, false);
}
}

/**
* Runs after delete.
* @param {QueryContext} queryContext
*/
public async $afterDelete(queryContext: QueryContext) {
await super.$afterDelete(queryContext);
await this.updateUncategorizedTransactionCount(queryContext, false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ export class DecrementUncategorizedTransactionOnMatching {
const transaction = await UncategorizedCashflowTransaction.query().findById(
uncategorizedTransactionId
);
//
await Account.query(trx)
.findById(transaction.accountId)
.decrement('uncategorizedTransactions', 1);
Expand All @@ -60,7 +59,6 @@ export class DecrementUncategorizedTransactionOnMatching {
const transaction = await UncategorizedCashflowTransaction.query().findById(
uncategorizedTransactionId
);
//
await Account.query(trx)
.findById(transaction.accountId)
.increment('uncategorizedTransactions', 1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ export class RegonizeTransactionsJob {
* Triggers sending invoice mail.
*/
private handler = async (job, done: Function) => {
const { tenantId } = job.attrs.data;
const { tenantId, batch } = job.attrs.data;
const regonizeTransactions = Container.get(RecognizeTranasctionsService);

try {
await regonizeTransactions.recognizeTransactions(tenantId);
await regonizeTransactions.recognizeTransactions(tenantId, batch);
done();
} catch (error) {
console.log(error);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import {
IBankRuleEventDeletedPayload,
IBankRuleEventEditedPayload,
} from '../../Rules/types';
import { IImportFileCommitedEventPayload } from '@/interfaces/Import';
import { Import } from '@/system/models';

@Service()
export class TriggerRecognizedTransactions {
Expand All @@ -27,6 +29,10 @@ export class TriggerRecognizedTransactions {
events.bankRules.onDeleted,
this.recognizedTransactionsOnRuleDeleted.bind(this)
);
bus.subscribe(
events.import.onImportCommitted,
this.triggerRecognizeTransactionsOnImportCommitted.bind(this)
);
}

/**
Expand Down Expand Up @@ -73,4 +79,20 @@ export class TriggerRecognizedTransactions {
const payload = { tenantId };
await this.agenda.now('recognize-uncategorized-transactions-job', payload);
}

/**
* Triggers the recognize bank transactions once the imported file commit.
* @param {IImportFileCommitedEventPayload} payload -
*/
private async triggerRecognizeTransactionsOnImportCommitted({
tenantId,
importId,
meta,
}: IImportFileCommitedEventPayload) {
const importFile = await Import.query().findOne({ importId });
const batch = importFile.paramsParsed.batch;
const payload = { tenantId, batch };

await this.agenda.now('recognize-uncategorized-transactions-job', payload);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,20 +84,23 @@ export class CategorizeCashflowTransaction {
cashflowTransactionDTO
);
// Updates the uncategorized transaction as categorized.
await UncategorizedCashflowTransaction.query(trx).patchAndFetchById(
uncategorizedTransactionId,
{
categorized: true,
categorizeRefType: 'CashflowTransaction',
categorizeRefId: cashflowTransaction.id,
}
);
const uncategorizedTransaction =
await UncategorizedCashflowTransaction.query(trx).patchAndFetchById(
uncategorizedTransactionId,
{
categorized: true,
categorizeRefType: 'CashflowTransaction',
categorizeRefId: cashflowTransaction.id,
}
);
// Triggers `onCashflowTransactionCategorized` event.
await this.eventPublisher.emitAsync(
events.cashflow.onTransactionCategorized,
{
tenantId,
// cashflowTransaction,
cashflowTransaction,
uncategorizedTransaction,
categorizeDTO,
trx,
} as ICashflowTransactionCategorizedPayload
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Inject, Service } from 'typedi';
import { Knex } from 'knex';
import * as yup from 'yup';
import uniqid from 'uniqid';
import { Importable } from '../Import/Importable';
import { CreateUncategorizedTransaction } from './CreateUncategorizedTransaction';
import { CreateUncategorizedTransactionDTO } from '@/interfaces';
Expand All @@ -15,6 +16,7 @@ export class UncategorizedTransactionsImportable extends Importable {

@Inject()
private tenancy: HasTenancyService;

/**
* Passing the sheet DTO to create uncategorized transaction.
* @param {number} tenantId
Expand Down Expand Up @@ -43,6 +45,7 @@ export class UncategorizedTransactionsImportable extends Importable {
return {
...createDTO,
accountId: context.import.paramsParsed.accountId,
batch: context.import.paramsParsed.batch,
};
}

Expand All @@ -54,6 +57,9 @@ export class UncategorizedTransactionsImportable extends Importable {
return BankTransactionsSampleData;
}

// ------------------
// # Params
// ------------------
/**
* Params validation schema.
* @returns {ValidationSchema[]}
Expand All @@ -79,4 +85,17 @@ export class UncategorizedTransactionsImportable extends Importable {
await Account.query().findById(params.accountId).throwIfNotFound({});
}
}

/**
* Transformes the import params before storing them.
* @param {Record<string, any>} parmas
*/
public transformParams(parmas: Record<string, any>) {
const batch = uniqid();

return {
...parmas,
batch,
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { Inject, Service } from 'typedi';
import events from '@/subscribers/events';
import HasTenancyService from '@/services/Tenancy/TenancyService';
import {
ICashflowTransactionCategorizedPayload,
ICashflowTransactionUncategorizedPayload,
} from '@/interfaces';

@Service()
export class DecrementUncategorizedTransactionOnCategorize {
@Inject()
private tenancy: HasTenancyService;
/**
* Constructor method.
*/
public attach(bus) {
bus.subscribe(
events.cashflow.onTransactionCategorized,
this.decrementUnCategorizedTransactionsOnCategorized.bind(this)
);
bus.subscribe(
events.cashflow.onTransactionUncategorized,
this.incrementUnCategorizedTransactionsOnUncategorized.bind(this)
);
}

/**
* Decrement the uncategoirzed transactions on the account once categorizing.
* @param {ICashflowTransactionCategorizedPayload}
*/
public async decrementUnCategorizedTransactionsOnCategorized({
tenantId,
uncategorizedTransaction,
}: ICashflowTransactionCategorizedPayload) {
const { Account } = this.tenancy.models(tenantId);

await Account.query()
.findById(uncategorizedTransaction.accountId)
.decrement('uncategorizedTransactions', 1);
}

/**
* Increment the uncategorized transaction on the given account on uncategorizing.
* @param {IManualJournalDeletingPayload}
*/
public async incrementUnCategorizedTransactionsOnUncategorized({
tenantId,
uncategorizedTransaction,
}: ICashflowTransactionUncategorizedPayload) {
const { Account } = this.tenancy.models(tenantId);

await Account.query()
.findById(uncategorizedTransaction.accountId)
.increment('uncategorizedTransactions', 1);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export class CashflowAccountTransactionReport extends FinancialSheet {
const firstMatchedTrans = first(matchedTrans);

return (
(firstCategorizedTrans?.id ||
firstCategorizedTrans?.id ||
firstMatchedTrans?.uncategorizedTransactionId ||
null
);
Expand Down
4 changes: 0 additions & 4 deletions packages/server/src/services/Import/ImportFileCommon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,10 @@ import { ServiceError } from '@/exceptions';
import { getUniqueImportableValue, trimObject } from './_utils';
import { ImportableResources } from './ImportableResources';
import ResourceService from '../Resource/ResourceService';
import HasTenancyService from '../Tenancy/TenancyService';
import { Import } from '@/system/models';

@Service()
export class ImportFileCommon {
@Inject()
private tenancy: HasTenancyService;

@Inject()
private importFileValidator: ImportFileDataValidator;

Expand Down
Loading

0 comments on commit d096e49

Please sign in to comment.