refactor(nestjs): banking modules

This commit is contained in:
Ahmed Bouhuolia
2025-06-03 21:42:09 +02:00
parent 5595478e19
commit f87bd341e9
33 changed files with 516 additions and 138 deletions

View File

@@ -76,6 +76,11 @@ const models = [
GetPendingBankAccountTransactions,
GetAutofillCategorizeTransactionService,
],
exports: [...models, RemovePendingUncategorizedTransaction],
exports: [
...models,
RemovePendingUncategorizedTransaction,
CommandBankTransactionValidator,
CreateBankTransactionService
],
})
export class BankingTransactionsModule {}

View File

@@ -15,6 +15,7 @@ import { GetUncategorizedTransactionsQueryDto } from './dtos/GetUncategorizedTra
import { GetPendingBankAccountTransactions } from './queries/GetPendingBankAccountTransaction.service';
import { GetPendingTransactionsQueryDto } from './dtos/GetPendingTransactionsQuery.dto';
import { GetAutofillCategorizeTransactionService } from './queries/GetAutofillCategorizeTransaction/GetAutofillCategorizeTransaction.service';
import { GetBankTransactionsQueryDto } from './dtos/GetBankTranasctionsQuery.dto';
@Injectable()
export class BankingTransactionsApplication {
@@ -54,7 +55,7 @@ export class BankingTransactionsApplication {
* Retrieves the bank transactions of the given bank id.
* @param {ICashflowAccountTransactionsQuery} query
*/
public getBankAccountTransactions(query: ICashflowAccountTransactionsQuery) {
public getBankAccountTransactions(query: GetBankTransactionsQueryDto) {
return this.getBankAccountTransactionsService.bankAccountTransactions(
query,
);

View File

@@ -1,3 +1,4 @@
import { Injectable } from '@nestjs/common';
import { includes, camelCase, upperFirst, sumBy } from 'lodash';
import { getCashflowTransactionType } from '../utils';
import {
@@ -6,7 +7,6 @@ import {
ERRORS,
} from '../constants';
import { Account } from '@/modules/Accounts/models/Account.model';
import { Injectable } from '@nestjs/common';
import { ServiceError } from '@/modules/Items/ServiceError';
import { BankTransaction } from '../models/BankTransaction';
import { UncategorizedBankTransaction } from '../models/UncategorizedBankTransaction';

View File

@@ -1,7 +1,6 @@
import { Inject, Injectable } from '@nestjs/common';
import { pick } from 'lodash';
import { Knex } from 'knex';
import * as R from 'ramda';
import * as composeAsync from 'async/compose';
import { CASHFLOW_TRANSACTION_TYPE } from '../constants';
import { transformCashflowTransactionType } from '../utils';
@@ -14,12 +13,12 @@ import { events } from '@/common/events/events';
import { Account } from '@/modules/Accounts/models/Account.model';
import { BankTransaction } from '../models/BankTransaction';
import {
ICashflowNewCommandDTO,
ICommandCashflowCreatedPayload,
ICommandCashflowCreatingPayload,
} from '../types/BankingTransactions.types';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { CreateBankTransactionDto } from '../dtos/CreateBankTransaction.dto';
import { formatDateFields } from '@/utils/format-date-fields';
@Injectable()
export class CreateBankTransactionService {
@@ -42,7 +41,7 @@ export class CreateBankTransactionService {
* @param {ICashflowNewCommandDTO} newCashflowTransactionDTO
*/
public authorize = async (
newCashflowTransactionDTO: ICashflowNewCommandDTO,
newCashflowTransactionDTO: CreateBankTransactionDto,
creditAccount: Account,
) => {
const transactionType = transformCashflowTransactionType(
@@ -60,7 +59,7 @@ export class CreateBankTransactionService {
/**
* Transformes owner contribution DTO to cashflow transaction.
* @param {ICashflowNewCommandDTO} newCashflowTransactionDTO - New transaction DTO.
* @param {CreateBankTransactionDto} newCashflowTransactionDTO - New transaction DTO.
* @returns {ICashflowTransactionInput} - Cashflow transaction object.
*/
private transformCashflowTransactionDTO = async (
@@ -91,7 +90,7 @@ export class CreateBankTransactionService {
const initialDTO = {
amount,
...fromDTO,
...formatDateFields(fromDTO, ['date']),
transactionNumber,
currencyCode: cashflowAccount.currencyCode,
exchangeRate: fromDTO?.exchangeRate || 1,
@@ -117,7 +116,7 @@ export class CreateBankTransactionService {
* @returns {Promise<ICashflowTransaction>}
*/
public newCashflowTransaction = async (
newTransactionDTO: ICashflowNewCommandDTO,
newTransactionDTO: CreateBankTransactionDto,
userId?: number,
): Promise<BankTransaction> => {
// Retrieves the cashflow account or throw not found error.

View File

@@ -1,47 +1,64 @@
import { ToNumber } from '@/common/decorators/Validators';
import {
IsBoolean,
IsDate,
IsDateString,
IsInt,
IsNotEmpty,
IsNumber,
IsOptional,
IsString,
} from 'class-validator';
export class CreateBankTransactionDto {
@IsDate()
@IsDateString()
@IsNotEmpty()
date: Date;
@IsString()
transactionNumber: string;
@IsOptional()
transactionNumber?: string;
@IsString()
referenceNo: string;
@IsOptional()
referenceNo?: string;
@IsNotEmpty()
@IsString()
transactionType: string;
@IsString()
description: string;
@IsNotEmpty()
@ToNumber()
@IsNumber()
amount: number;
@ToNumber()
@IsNumber()
exchangeRate: number;
exchangeRate: number = 1;
@IsString()
@IsOptional()
currencyCode: string;
@IsNumber()
@IsNotEmpty()
@ToNumber()
@IsInt()
creditAccountId: number;
@IsNumber()
@IsNotEmpty()
@ToNumber()
@IsInt()
cashflowAccountId: number;
@IsBoolean()
publish: boolean;
@IsOptional()
publish: boolean = true;
@IsOptional()
@IsNumber()
@ToNumber()
@IsInt()
branchId?: number;
@IsOptional()
@@ -53,6 +70,6 @@ export class CreateBankTransactionDto {
plaidAccountId?: string;
@IsOptional()
@IsNumber()
@IsInt()
uncategorizedTransactionId?: number;
}

View File

@@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common';
import { getBankAccountTransactionsDefaultQuery } from './_utils';
import { GetBankAccountTransactionsRepository } from './GetBankAccountTransactionsRepo.service';
import { GetBankAccountTransactions } from './GetBankAccountTransactions';
import { ICashflowAccountTransactionsQuery } from '../../types/BankingTransactions.types';
import { GetBankTransactionsQueryDto } from '../../dtos/GetBankTranasctionsQuery.dto';
@Injectable()
export class GetBankAccountTransactionsService {
@@ -16,7 +16,7 @@ export class GetBankAccountTransactionsService {
* @return {Promise<IInvetoryItemDetailDOO>}
*/
public async bankAccountTransactions(
query: ICashflowAccountTransactionsQuery,
query: GetBankTransactionsQueryDto,
) {
const parsedQuery = {
...getBankAccountTransactionsDefaultQuery(),

View File

@@ -1,35 +1,23 @@
import { Inject, Injectable } from '@nestjs/common';
import { initialize } from 'objection';
import { Knex } from 'knex';
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
import { UncategorizedBankTransaction } from '../models/UncategorizedBankTransaction';
import { UncategorizedTransactionTransformer } from '../../BankingCategorize/commands/UncategorizedTransaction.transformer';
import { GetUncategorizedTransactionsQueryDto } from '../dtos/GetUncategorizedTransactionsQuery.dto';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { TENANCY_DB_CONNECTION } from '@/modules/Tenancy/TenancyDB/TenancyDB.constants';
import { Account } from '@/modules/Accounts/models/Account.model';
import { RecognizedBankTransaction } from '@/modules/BankingTranasctionsRegonize/models/RecognizedBankTransaction';
import { MatchedBankTransaction } from '@/modules/BankingMatching/models/MatchedBankTransaction';
@Injectable()
export class GetUncategorizedTransactions {
/**
* @param {TransformerInjectable} transformer
* @param {UncategorizedBankTransaction.name} uncategorizedBankTransactionModel
*/
constructor(
private readonly transformer: TransformerInjectable,
@Inject(TENANCY_DB_CONNECTION)
private readonly tenantDb: () => Knex,
@Inject(UncategorizedBankTransaction.name)
private readonly uncategorizedBankTransactionModel: TenantModelProxy<typeof UncategorizedBankTransaction>,
@Inject(Account.name)
private readonly accountModel: TenantModelProxy<typeof Account>,
@Inject(RecognizedBankTransaction.name)
private readonly recognizedTransactionModel: TenantModelProxy<typeof RecognizedBankTransaction>,
@Inject(MatchedBankTransaction.name)
private readonly matchedTransactionModel: TenantModelProxy<typeof MatchedBankTransaction>,
private readonly uncategorizedBankTransactionModel: TenantModelProxy<
typeof UncategorizedBankTransaction
>,
) {}
/**
@@ -39,7 +27,7 @@ export class GetUncategorizedTransactions {
*/
public async getTransactions(
accountId: number,
query: GetUncategorizedTransactionsQueryDto
query: GetUncategorizedTransactionsQueryDto,
) {
// Parsed query with default values.
const _query = {
@@ -47,16 +35,9 @@ export class GetUncategorizedTransactions {
pageSize: 20,
...query,
};
await initialize(this.tenantDb(), [
this.accountModel(),
this.uncategorizedBankTransactionModel(),
this.recognizedTransactionModel(),
this.matchedTransactionModel(),
]);
const { results, pagination } =
await this.uncategorizedBankTransactionModel().query()
await this.uncategorizedBankTransactionModel()
.query()
.onBuild((q) => {
q.where('accountId', accountId);
q.where('categorized', false);
@@ -89,7 +70,7 @@ export class GetUncategorizedTransactions {
const data = await this.transformer.transform(
results,
new UncategorizedTransactionTransformer()
new UncategorizedTransactionTransformer(),
);
return {
data,

View File

@@ -3,7 +3,10 @@ import { OnEvent } from '@nestjs/event-emitter';
import { BankTransactionAutoIncrement } from '../commands/BankTransactionAutoIncrement.service';
import { BankTransactionGLEntriesService } from '../commands/BankTransactionGLEntries';
import { events } from '@/common/events/events';
import { ICommandCashflowCreatedPayload, ICommandCashflowDeletedPayload } from '../types/BankingTransactions.types';
import {
ICommandCashflowCreatedPayload,
ICommandCashflowDeletedPayload,
} from '../types/BankingTransactions.types';
@Injectable()
export class BankingTransactionGLEntriesSubscriber {
@@ -56,5 +59,5 @@ export class BankingTransactionGLEntriesSubscriber {
cashflowTransactionId,
trx,
);
};
}
}