refactor(nestjs): banking module

This commit is contained in:
Ahmed Bouhuolia
2025-06-02 15:41:41 +02:00
parent deadd5ac80
commit 7247b52fe5
22 changed files with 573 additions and 106 deletions

View File

@@ -1,51 +0,0 @@
import {
Body,
Controller,
Delete,
Get,
Param,
Post,
Query,
} from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { BankingTransactionsApplication } from './BankingTransactionsApplication.service';
import { CreateBankTransactionDto } from './dtos/CreateBankTransaction.dto';
import { GetBankTransactionsQueryDto } from './dtos/GetBankTranasctionsQuery.dto';
@Controller('banking/transactions')
@ApiTags('banking-transactions')
export class BankingTransactionsController {
constructor(
private readonly bankingTransactionsApplication: BankingTransactionsApplication,
) {}
@Get()
async getBankAccountTransactions(
@Query() query: GetBankTransactionsQueryDto,
) {
return this.bankingTransactionsApplication.getBankAccountTransactions(
query,
);
}
@Post()
async createTransaction(@Body() transactionDTO: CreateBankTransactionDto) {
return this.bankingTransactionsApplication.createTransaction(
transactionDTO,
);
}
@Delete(':id')
async deleteTransaction(@Param('id') transactionId: string) {
return this.bankingTransactionsApplication.deleteTransaction(
Number(transactionId),
);
}
@Get(':id')
async getTransaction(@Param('id') transactionId: string) {
return this.bankingTransactionsApplication.getTransaction(
Number(transactionId),
);
}
}

View File

@@ -19,13 +19,18 @@ import { CommandBankTransactionValidator } from './commands/CommandCasflowValida
import { BranchTransactionDTOTransformer } from '../Branches/integrations/BranchTransactionDTOTransform';
import { BranchesModule } from '../Branches/Branches.module';
import { RemovePendingUncategorizedTransaction } from './commands/RemovePendingUncategorizedTransaction.service';
import { BankingTransactionsController } from './BankingTransactions.controller';
import { BankingTransactionsController } from './controllers/BankingTransactions.controller';
import { GetBankAccountsService } from './queries/GetBankAccounts.service';
import { DynamicListModule } from '../DynamicListing/DynamicList.module';
import { BankAccount } from './models/BankAccount';
import { LedgerModule } from '../Ledger/Ledger.module';
import { GetBankAccountTransactionsService } from './queries/GetBankAccountTransactions/GetBankAccountTransactions.service';
import { GetBankAccountTransactionsRepository } from './queries/GetBankAccountTransactions/GetBankAccountTransactionsRepo.service';
import { GetUncategorizedTransactions } from './queries/GetUncategorizedTransactions';
import { GetUncategorizedBankTransactionService } from './queries/GetUncategorizedBankTransaction.service';
import { BankingUncategorizedTransactionsController } from './controllers/BankingUncategorizedTransactions.controller';
import { BankingPendingTransactionsController } from './controllers/BankingPendingTransactions.controller';
import { GetPendingBankAccountTransactions } from './queries/GetPendingBankAccountTransaction.service';
const models = [
RegisterTenancyModel(UncategorizedBankTransaction),
@@ -42,7 +47,11 @@ const models = [
DynamicListModule,
...models,
],
controllers: [BankingTransactionsController],
controllers: [
BankingTransactionsController,
BankingUncategorizedTransactionsController,
BankingPendingTransactionsController,
],
providers: [
BankTransactionAutoIncrement,
BankTransactionGLEntriesService,
@@ -61,6 +70,9 @@ const models = [
RemovePendingUncategorizedTransaction,
GetBankAccountTransactionsRepository,
GetBankAccountTransactionsService,
GetUncategorizedTransactions,
GetUncategorizedBankTransactionService,
GetPendingBankAccountTransactions
],
exports: [...models, RemovePendingUncategorizedTransaction],
})

View File

@@ -9,6 +9,11 @@ import {
import { GetBankAccountsService } from './queries/GetBankAccounts.service';
import { CreateBankTransactionDto } from './dtos/CreateBankTransaction.dto';
import { GetBankAccountTransactionsService } from './queries/GetBankAccountTransactions/GetBankAccountTransactions.service';
import { GetUncategorizedTransactions } from './queries/GetUncategorizedTransactions';
import { GetUncategorizedBankTransactionService } from './queries/GetUncategorizedBankTransaction.service';
import { GetUncategorizedTransactionsQueryDto } from './dtos/GetUncategorizedTransactionsQuery.dto';
import { GetPendingBankAccountTransactions } from './queries/GetPendingBankAccountTransaction.service';
import { GetPendingTransactionsQueryDto } from './dtos/GetPendingTransactionsQuery.dto';
@Injectable()
export class BankingTransactionsApplication {
@@ -18,6 +23,9 @@ export class BankingTransactionsApplication {
private readonly getCashflowTransactionService: GetBankTransactionService,
private readonly getBankAccountsService: GetBankAccountsService,
private readonly getBankAccountTransactionsService: GetBankAccountTransactionsService,
private readonly getBankAccountUncategorizedTransitionsService: GetUncategorizedTransactions,
private readonly getBankAccountUncategorizedTransactionService: GetUncategorizedBankTransactionService,
private readonly getPendingBankAccountTransactionsService: GetPendingBankAccountTransactions
) {}
/**
@@ -68,4 +76,37 @@ export class BankingTransactionsApplication {
public getBankAccounts(filterDTO: IBankAccountsFilter) {
return this.getBankAccountsService.getBankAccounts(filterDTO);
}
/**
* Retrieves the uncategorized cashflow transactions.
* @param {number} accountId - Account id.
* @param {IGetUncategorizedTransactionsQuery} query - Query.
*/
public getBankAccountUncategorizedTransactions(
accountId: number,
query: GetUncategorizedTransactionsQueryDto,
) {
return this.getBankAccountUncategorizedTransitionsService.getTransactions(
accountId,
query,
);
}
/**
* Retrieves specific uncategorized cashflow transaction.
* @param {number} uncategorizedTransactionId - Uncategorized transaction id.
*/
public getUncategorizedTransaction(uncategorizedTransactionId: number) {
return this.getBankAccountUncategorizedTransactionService.getTransaction(
uncategorizedTransactionId,
);
}
/**
* Retrieves the pending bank account transactions.
* @param {GetPendingTransactionsQueryDto} filter - Pending transactions query.
*/
public getPendingBankAccountTransactions(filter?: GetPendingTransactionsQueryDto) {
return this.getPendingBankAccountTransactionsService.getPendingTransactions(filter);
}
}

View File

@@ -0,0 +1,42 @@
import { Controller, Get, Query } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiResponse, ApiQuery } from '@nestjs/swagger';
import { BankingTransactionsApplication } from '../BankingTransactionsApplication.service';
import { GetPendingTransactionsQueryDto } from '../dtos/GetPendingTransactionsQuery.dto';
@Controller('banking/pending')
@ApiTags('banking-pending')
export class BankingPendingTransactionsController {
constructor(
private readonly bankingTransactionsApplication: BankingTransactionsApplication,
) {}
@Get()
@ApiOperation({ summary: 'Get pending bank account transactions' })
@ApiResponse({
status: 200,
description: 'Returns a list of pending bank account transactions',
})
@ApiQuery({
name: 'page',
required: false,
type: Number,
description: 'Page number for pagination',
})
@ApiQuery({
name: 'pageSize',
required: false,
type: Number,
description: 'Number of items per page',
})
@ApiQuery({
name: 'accountId',
required: false,
type: Number,
description: 'Filter by bank account ID',
})
async getPendingTransactions(@Query() query: GetPendingTransactionsQueryDto) {
return this.bankingTransactionsApplication.getPendingBankAccountTransactions(
query,
);
}
}

View File

@@ -0,0 +1,108 @@
import {
Body,
Controller,
Delete,
Get,
Param,
Post,
Query,
} from '@nestjs/common';
import { ApiTags, ApiOperation, ApiResponse, ApiParam, ApiQuery, ApiBody } from '@nestjs/swagger';
import { BankingTransactionsApplication } from '../BankingTransactionsApplication.service';
import { CreateBankTransactionDto } from '../dtos/CreateBankTransaction.dto';
import { GetBankTransactionsQueryDto } from '../dtos/GetBankTranasctionsQuery.dto';
@Controller('banking/transactions')
@ApiTags('banking-transactions')
export class BankingTransactionsController {
constructor(
private readonly bankingTransactionsApplication: BankingTransactionsApplication,
) {}
@Get()
@ApiOperation({ summary: 'Get bank account transactions' })
@ApiResponse({
status: 200,
description: 'Returns a list of bank account transactions',
})
@ApiQuery({
name: 'page',
required: false,
type: Number,
description: 'Page number for pagination',
})
@ApiQuery({
name: 'pageSize',
required: false,
type: Number,
description: 'Number of items per page',
})
async getBankAccountTransactions(
@Query() query: GetBankTransactionsQueryDto,
) {
return this.bankingTransactionsApplication.getBankAccountTransactions(
query,
);
}
@Post()
@ApiOperation({ summary: 'Create a new bank transaction' })
@ApiResponse({
status: 201,
description: 'The bank transaction has been successfully created',
})
@ApiResponse({
status: 400,
description: 'Invalid input data',
})
@ApiBody({ type: CreateBankTransactionDto })
async createTransaction(@Body() transactionDTO: CreateBankTransactionDto) {
return this.bankingTransactionsApplication.createTransaction(
transactionDTO,
);
}
@Delete(':id')
@ApiOperation({ summary: 'Delete a bank transaction' })
@ApiResponse({
status: 200,
description: 'The bank transaction has been successfully deleted',
})
@ApiResponse({
status: 404,
description: 'Bank transaction not found',
})
@ApiParam({
name: 'id',
required: true,
type: String,
description: 'Bank transaction ID',
})
async deleteTransaction(@Param('id') transactionId: string) {
return this.bankingTransactionsApplication.deleteTransaction(
Number(transactionId),
);
}
@Get(':id')
@ApiOperation({ summary: 'Get a specific bank transaction by ID' })
@ApiResponse({
status: 200,
description: 'Returns the bank transaction details',
})
@ApiResponse({
status: 404,
description: 'Bank transaction not found',
})
@ApiParam({
name: 'id',
required: true,
type: String,
description: 'Bank transaction ID',
})
async getTransaction(@Param('id') transactionId: string) {
return this.bankingTransactionsApplication.getTransaction(
Number(transactionId),
);
}
}

View File

@@ -0,0 +1,70 @@
import { Controller, Get, Param, Query } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiResponse, ApiParam, ApiQuery } from '@nestjs/swagger';
import { GetUncategorizedTransactionsQueryDto } from '../dtos/GetUncategorizedTransactionsQuery.dto';
import { BankingTransactionsApplication } from '../BankingTransactionsApplication.service';
@Controller('banking/uncategorized')
@ApiTags('banking-uncategorized')
export class BankingUncategorizedTransactionsController {
constructor(
private readonly bankingTransactionsApplication: BankingTransactionsApplication,
) {}
@Get('accounts/:accountId')
@ApiOperation({ summary: 'Get uncategorized transactions for a specific bank account' })
@ApiResponse({
status: 200,
description: 'Returns a list of uncategorized transactions for the specified bank account',
})
@ApiParam({
name: 'accountId',
required: true,
type: Number,
description: 'Bank account ID',
})
@ApiQuery({
name: 'page',
required: false,
type: Number,
description: 'Page number for pagination',
})
@ApiQuery({
name: 'pageSize',
required: false,
type: Number,
description: 'Number of items per page',
})
async getBankAccountUncategorizedTransactions(
@Param('accountId') accountId: number,
@Query() query: GetUncategorizedTransactionsQueryDto,
) {
return this.bankingTransactionsApplication.getBankAccountUncategorizedTransactions(
accountId,
query,
);
}
@Get(':uncategorizedTransactionId')
@ApiOperation({ summary: 'Get a specific uncategorized transaction by ID' })
@ApiResponse({
status: 200,
description: 'Returns the uncategorized transaction details',
})
@ApiResponse({
status: 404,
description: 'Uncategorized transaction not found',
})
@ApiParam({
name: 'uncategorizedTransactionId',
required: true,
type: Number,
description: 'Uncategorized transaction ID',
})
async getUncategorizedTransaction(
@Param('uncategorizedTransactionId') uncategorizedTransactionId: number,
) {
return this.bankingTransactionsApplication.getUncategorizedTransaction(
Number(uncategorizedTransactionId),
);
}
}

View File

@@ -6,23 +6,47 @@ import {
} from 'class-validator';
import { NumberFormatQueryDto } from './NumberFormatQuery.dto';
import { Type } from 'class-transformer';
import { ApiProperty } from '@nestjs/swagger';
export class GetBankTransactionsQueryDto {
@IsOptional()
@Type(() => Number)
@IsNumber()
@ApiProperty({
description: 'Page number for pagination',
required: false,
type: Number,
example: 1
})
page: number;
@IsOptional()
@Type(() => Number)
@IsNumber()
@ApiProperty({
description: 'Number of items per page',
required: false,
type: Number,
example: 10
})
pageSize: number;
@IsNotEmpty()
@Type(() => Number)
@IsNumber()
@ApiProperty({
description: 'Bank account ID',
required: true,
type: Number,
example: 1
})
accountId: number;
@IsOptional()
@ApiProperty({
description: 'Number format options',
required: false,
type: NumberFormatQueryDto
})
numberFormat: NumberFormatQueryDto;
}

View File

@@ -0,0 +1,31 @@
import { IsOptional } from "class-validator";
import { ApiProperty } from "@nestjs/swagger";
export class GetPendingTransactionsQueryDto {
@IsOptional()
@ApiProperty({
description: 'Page number for pagination',
required: false,
type: Number,
example: 1
})
page?: number;
@IsOptional()
@ApiProperty({
description: 'Number of items per page',
required: false,
type: Number,
example: 10
})
pageSize?: number;
@IsOptional()
@ApiProperty({
description: 'Filter by bank account ID',
required: false,
type: Number,
example: 1
})
accountId?: number;
}

View File

@@ -0,0 +1,58 @@
import { IsOptional } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';
export class GetUncategorizedTransactionsQueryDto {
@IsOptional()
@ApiProperty({
description: 'Page number for pagination',
required: false,
type: Number,
example: 1
})
page?: number;
@IsOptional()
@ApiProperty({
description: 'Number of items per page',
required: false,
type: Number,
example: 10
})
pageSize?: number;
@IsOptional()
@ApiProperty({
description: 'Minimum date for filtering transactions',
required: false,
type: Date,
example: '2023-01-01'
})
minDate?: Date;
@IsOptional()
@ApiProperty({
description: 'Maximum date for filtering transactions',
required: false,
type: Date,
example: '2023-12-31'
})
maxDate?: Date;
@IsOptional()
@ApiProperty({
description: 'Minimum amount for filtering transactions',
required: false,
type: Number,
example: 100
})
minAmount?: number;
@IsOptional()
@ApiProperty({
description: 'Maximum amount for filtering transactions',
required: false,
type: Number,
example: 1000
})
maxAmount?: number;
}

View File

@@ -2,6 +2,8 @@ import { Inject, Injectable } from '@nestjs/common';
import { GetPendingBankAccountTransactionTransformer } from './GetPendingBankAccountTransactionTransformer';
import { UncategorizedBankTransaction } from '../models/UncategorizedBankTransaction';
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { GetPendingTransactionsQueryDto } from '../dtos/GetPendingTransactionsQuery.dto';
@Injectable()
export class GetPendingBankAccountTransactions {
@@ -9,40 +11,37 @@ export class GetPendingBankAccountTransactions {
private readonly transformerService: TransformerInjectable,
@Inject(UncategorizedBankTransaction.name)
private readonly uncategorizedBankTransactionModel: typeof UncategorizedBankTransaction
private readonly uncategorizedBankTransactionModel: TenantModelProxy<
typeof UncategorizedBankTransaction
>,
) {}
/**
* Retrieves the given bank accounts pending transaction.
* @param {GetPendingTransactionsQuery} filter - Pending transactions query.
* @param {GetPendingTransactionsQueryDto} filter - Pending transactions query.
*/
async getPendingTransactions(filter?: GetPendingTransactionsQuery) {
async getPendingTransactions(filter?: GetPendingTransactionsQueryDto) {
const _filter = {
page: 1,
page: 1,
pageSize: 20,
...filter,
};
const { results, pagination } =
await this.uncategorizedBankTransactionModel.query()
await this.uncategorizedBankTransactionModel()
.query()
.onBuild((q) => {
q.modify('pending');
if (_filter?.accountId) {
q.where('accountId', _filter.accountId);
}
})
.pagination(_filter.page - 1, _filter.pageSize);
if (_filter?.accountId) {
q.where('accountId', _filter.accountId);
}
})
.pagination(_filter.page - 1, _filter.pageSize);
const data = await this.transformerService.transform(
results,
new GetPendingBankAccountTransactionTransformer()
new GetPendingBankAccountTransactionTransformer(),
);
return { data, pagination };
}
}
interface GetPendingTransactionsQuery {
page?: number;
pageSize?: number;
accountId?: number;
}

View File

@@ -1,39 +0,0 @@
import { Inject, Injectable } from '@nestjs/common';
import { GetRecognizedTransactionTransformer } from './GetRecognizedTransactionTransformer';
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
import { UncategorizedBankTransaction } from '../models/UncategorizedBankTransaction';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
@Injectable()
export class GetRecognizedTransactionService {
constructor(
private readonly transformer: TransformerInjectable,
@Inject(UncategorizedBankTransaction.name)
private readonly uncategorizedBankTransactionModel: TenantModelProxy<
typeof UncategorizedBankTransaction
>,
) {}
/**
* Retrieves the recognized transaction of the given uncategorized transaction.
* @param {number} tenantId
* @param {number} uncategorizedTransactionId
*/
public async getRecognizedTransaction(uncategorizedTransactionId: number) {
const uncategorizedTransaction =
await this.uncategorizedBankTransactionModel()
.query()
.findById(uncategorizedTransactionId)
.withGraphFetched('matchedBankTransactions')
.withGraphFetched('recognizedTransaction.assignAccount')
.withGraphFetched('recognizedTransaction.bankRule')
.withGraphFetched('account')
.throwIfNotFound();
return this.transformer.transform(
uncategorizedTransaction,
new GetRecognizedTransactionTransformer(),
);
}
}

View File

@@ -1,261 +0,0 @@
import { Transformer } from "@/modules/Transformer/Transformer";
export class GetRecognizedTransactionTransformer extends Transformer {
/**
* Include these attributes to sale credit note object.
* @returns {Array}
*/
public includeAttributes = (): string[] => {
return [
'uncategorizedTransactionId',
'referenceNo',
'description',
'payee',
'amount',
'formattedAmount',
'date',
'formattedDate',
'assignedAccountId',
'assignedAccountName',
'assignedAccountCode',
'assignedPayee',
'assignedMemo',
'assignedCategory',
'assignedCategoryFormatted',
'withdrawal',
'deposit',
'isDepositTransaction',
'isWithdrawalTransaction',
'formattedDepositAmount',
'formattedWithdrawalAmount',
'bankRuleId',
'bankRuleName',
];
};
/**
* Exclude all attributes.
* @returns {Array<string>}
*/
public excludeAttributes = (): string[] => {
return ['*'];
};
/**
* Get the uncategorized transaction id.
* @param transaction
* @returns {number}
*/
public uncategorizedTransactionId = (transaction): number => {
return transaction.id;
}
/**
* Get the reference number of the transaction.
* @param {object} transaction
* @returns {string}
*/
public referenceNo(transaction: any): string {
return transaction.referenceNo;
}
/**
* Get the description of the transaction.
* @param {object} transaction
* @returns {string}
*/
public description(transaction: any): string {
return transaction.description;
}
/**
* Get the payee of the transaction.
* @param {object} transaction
* @returns {string}
*/
public payee(transaction: any): string {
return transaction.payee;
}
/**
* Get the amount of the transaction.
* @param {object} transaction
* @returns {number}
*/
public amount(transaction: any): number {
return transaction.amount;
}
/**
* Get the formatted amount of the transaction.
* @param {object} transaction
* @returns {string}
*/
public formattedAmount(transaction: any): string {
return this.formatNumber(transaction.formattedAmount, {
money: true,
});
}
/**
* Get the date of the transaction.
* @param {object} transaction
* @returns {string}
*/
public date(transaction: any): string {
return transaction.date;
}
/**
* Get the formatted date of the transaction.
* @param {object} transaction
* @returns {string}
*/
public formattedDate(transaction: any): string {
return this.formatDate(transaction.date);
}
/**
* Get the assigned account ID of the transaction.
* @param {object} transaction
* @returns {number}
*/
public assignedAccountId(transaction: any): number {
return transaction.recognizedTransaction.assignedAccountId;
}
/**
* Get the assigned account name of the transaction.
* @param {object} transaction
* @returns {string}
*/
public assignedAccountName(transaction: any): string {
return transaction.recognizedTransaction.assignAccount.name;
}
/**
* Get the assigned account code of the transaction.
* @param {object} transaction
* @returns {string}
*/
public assignedAccountCode(transaction: any): string {
return transaction.recognizedTransaction.assignAccount.code;
}
/**
* Get the assigned payee of the transaction.
* @param {object} transaction
* @returns {string}
*/
public getAssignedPayee(transaction: any): string {
return transaction.recognizedTransaction.assignedPayee;
}
/**
* Get the assigned memo of the transaction.
* @param {object} transaction
* @returns {string}
*/
public assignedMemo(transaction: any): string {
return transaction.recognizedTransaction.assignedMemo;
}
/**
* Get the assigned category of the transaction.
* @param {object} transaction
* @returns {string}
*/
public assignedCategory(transaction: any): string {
return transaction.recognizedTransaction.assignedCategory;
}
/**
*
* @returns {string}
*/
public assignedCategoryFormatted() {
return 'Other Income'
}
/**
* Check if the transaction is a withdrawal.
* @param {object} transaction
* @returns {boolean}
*/
public isWithdrawal(transaction: any): boolean {
return transaction.withdrawal;
}
/**
* Check if the transaction is a deposit.
* @param {object} transaction
* @returns {boolean}
*/
public isDeposit(transaction: any): boolean {
return transaction.deposit;
}
/**
* Check if the transaction is a deposit transaction.
* @param {object} transaction
* @returns {boolean}
*/
public isDepositTransaction(transaction: any): boolean {
return transaction.isDepositTransaction;
}
/**
* Check if the transaction is a withdrawal transaction.
* @param {object} transaction
* @returns {boolean}
*/
public isWithdrawalTransaction(transaction: any): boolean {
return transaction.isWithdrawalTransaction;
}
/**
* Get formatted deposit amount.
* @param {any} transaction
* @returns {string}
*/
protected formattedDepositAmount(transaction) {
if (transaction.isDepositTransaction) {
return this.formatNumber(transaction.deposit, {
currencyCode: transaction.currencyCode,
});
}
return '';
}
/**
* Get formatted withdrawal amount.
* @param transaction
* @returns {string}
*/
protected formattedWithdrawalAmount(transaction) {
if (transaction.isWithdrawalTransaction) {
return this.formatNumber(transaction.withdrawal, {
currencyCode: transaction.currencyCode,
});
}
return '';
}
/**
* Get the transaction bank rule id.
* @param transaction
* @returns {string}
*/
protected bankRuleId(transaction) {
return transaction.recognizedTransaction.bankRuleId;
}
/**
* Get the transaction bank rule name.
* @param transaction
* @returns {string}
*/
protected bankRuleName(transaction) {
return transaction.recognizedTransaction.bankRule.name;
}
}

View File

@@ -1,67 +0,0 @@
import { Inject, Injectable } from '@nestjs/common';
import { GetRecognizedTransactionTransformer } from './GetRecognizedTransactionTransformer';
import { UncategorizedBankTransaction } from '../models/UncategorizedBankTransaction';
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
import { IGetRecognizedTransactionsQuery } from '../types/BankingTransactions.types';
@Injectable()
export class GetRecognizedTransactionsService {
constructor(
private readonly transformer: TransformerInjectable,
@Inject(UncategorizedBankTransaction.name)
private readonly uncategorizedBankTransactionModel: typeof UncategorizedBankTransaction,
) {}
/**
* Retrieves the recognized transactions of the given account.
* @param {number} tenantId
* @param {IGetRecognizedTransactionsQuery} filter -
*/
async getRecognizedTranactions(filter?: IGetRecognizedTransactionsQuery) {
const _query = {
page: 1,
pageSize: 20,
...filter,
};
const { results, pagination } =
await this.uncategorizedBankTransactionModel.query()
.onBuild((q) => {
q.withGraphFetched('recognizedTransaction.assignAccount');
q.withGraphFetched('recognizedTransaction.bankRule');
q.whereNotNull('recognizedTransactionId');
// Exclude the excluded transactions.
q.modify('notExcluded');
// Exclude the pending transactions.
q.modify('notPending');
if (_query.accountId) {
q.where('accountId', _query.accountId);
}
if (_query.minDate) {
q.modify('fromDate', _query.minDate);
}
if (_query.maxDate) {
q.modify('toDate', _query.maxDate);
}
if (_query.minAmount) {
q.modify('minAmount', _query.minAmount);
}
if (_query.maxAmount) {
q.modify('maxAmount', _query.maxAmount);
}
if (_query.accountId) {
q.where('accountId', _query.accountId);
}
})
.pagination(_query.page - 1, _query.pageSize);
const data = await this.transformer.transform(
results,
new GetRecognizedTransactionTransformer(),
);
return { data, pagination };
}
}

View File

@@ -1,26 +1,45 @@
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 { Inject, Injectable } from '@nestjs/common';
import { UncategorizedTransactionTransformer } from '../../BankingCategorize/commands/UncategorizedTransaction.transformer';
import { IGetUncategorizedTransactionsQuery } from '../types/BankingTransactions.types';
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 {
constructor(
private readonly transformer: TransformerInjectable,
@Inject(TENANCY_DB_CONNECTION)
private readonly tenantDb: () => Knex,
@Inject(UncategorizedBankTransaction.name)
private readonly uncategorizedBankTransactionModel: typeof UncategorizedBankTransaction,
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>,
) {}
/**
* Retrieves the uncategorized cashflow transactions.
* @param {number} tenantId - Tenant id.
* @param {number} accountId - Account Id.
* @param {IGetUncategorizedTransactionsQuery} query - Query.
*/
public async getTransactions(
accountId: number,
query: IGetUncategorizedTransactionsQuery
query: GetUncategorizedTransactionsQueryDto
) {
// Parsed query with default values.
const _query = {
@@ -29,8 +48,15 @@ export class GetUncategorizedTransactions {
...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);