Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Matching transactions bugs #523

Merged
merged 4 commits into from
Jul 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading