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

@@ -183,9 +183,9 @@ import { BankingPlaidModule } from '../BankingPlaid/BankingPlaid.module';
LedgerModule,
BankAccountsModule,
BankRulesModule,
BankingTransactionsModule,
BankingTransactionsExcludeModule,
BankingTransactionsRegonizeModule,
BankingTransactionsModule,
BankingMatchingModule,
BankingPlaidModule,
TransactionsLockingModule,

View File

@@ -0,0 +1,26 @@
import { Controller, Get, Param, Query } from '@nestjs/common';
import { BankingTransactionsApplication } from '../BankingTransactions/BankingTransactionsApplication.service';
import { ApiTags } from '@nestjs/swagger';
import { RecognizedTransactionsApplication } from './RecognizedTransactions.application';
@Controller('banking/recognized')
@ApiTags('banking-recognized')
export class BankingRecognizedTransactionsController {
constructor(
private readonly recognizedTransactionsApplication: RecognizedTransactionsApplication,
) {}
@Get(':recognizedTransactionId')
async getRecognizedTransaction(
@Param('recognizedTransactionId') recognizedTransactionId: number,
) {
return this.recognizedTransactionsApplication.getRecognizedTransaction(
Number(recognizedTransactionId),
);
}
@Get()
async getRecognizedTransactions(@Query() query: any) {
return this.recognizedTransactionsApplication.getRecognizedTransactions(query);
}
}

View File

@@ -7,6 +7,10 @@ import { RecognizeTranasctionsService } from './commands/RecognizeTranasctions.s
import { TriggerRecognizedTransactionsSubscriber } from './events/TriggerRecognizedTransactions';
import { BankingTransactionsModule } from '../BankingTransactions/BankingTransactions.module';
import { BankRulesModule } from '../BankRules/BankRules.module';
import { BankingRecognizedTransactionsController } from './BankingRecognizedTransactions.controller';
import { RecognizedTransactionsApplication } from './RecognizedTransactions.application';
import { GetRecognizedTransactionsService } from './GetRecongizedTransactions';
import { GetRecognizedTransactionService } from './queries/GetRecognizedTransaction.service';
const models = [RegisterTenancyModel(RecognizedBankTransaction)];
@@ -17,10 +21,13 @@ const models = [RegisterTenancyModel(RecognizedBankTransaction)];
...models,
],
providers: [
RecognizedTransactionsApplication,
GetRecognizedTransactionsService,
GetAutofillCategorizeTransactionService,
RevertRecognizedTransactionsService,
RecognizeTranasctionsService,
TriggerRecognizedTransactionsSubscriber,
GetRecognizedTransactionService,
],
exports: [
...models,
@@ -28,5 +35,6 @@ const models = [RegisterTenancyModel(RecognizedBankTransaction)];
RevertRecognizedTransactionsService,
RecognizeTranasctionsService,
],
controllers: [BankingRecognizedTransactionsController],
})
export class BankingTransactionsRegonizeModule {}

View File

@@ -1,8 +1,9 @@
import { Inject, Injectable } from '@nestjs/common';
import { GetRecognizedTransactionTransformer } from './GetRecognizedTransactionTransformer';
import { UncategorizedBankTransaction } from '../models/UncategorizedBankTransaction';
import { GetRecognizedTransactionTransformer } from './queries/GetRecognizedTransactionTransformer';
import { UncategorizedBankTransaction } from '../BankingTransactions/models/UncategorizedBankTransaction';
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
import { IGetRecognizedTransactionsQuery } from '../types/BankingTransactions.types';
import { IGetRecognizedTransactionsQuery } from '../BankingTransactions/types/BankingTransactions.types';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
@Injectable()
export class GetRecognizedTransactionsService {
@@ -10,7 +11,7 @@ export class GetRecognizedTransactionsService {
private readonly transformer: TransformerInjectable,
@Inject(UncategorizedBankTransaction.name)
private readonly uncategorizedBankTransactionModel: typeof UncategorizedBankTransaction,
private readonly uncategorizedBankTransactionModel: TenantModelProxy<typeof UncategorizedBankTransaction>,
) {}
/**
@@ -25,7 +26,7 @@ export class GetRecognizedTransactionsService {
...filter,
};
const { results, pagination } =
await this.uncategorizedBankTransactionModel.query()
await this.uncategorizedBankTransactionModel().query()
.onBuild((q) => {
q.withGraphFetched('recognizedTransaction.assignAccount');
q.withGraphFetched('recognizedTransaction.bankRule');

View File

@@ -0,0 +1,70 @@
import { Knex } from 'knex';
import { Injectable } from '@nestjs/common';
import { GetRecognizedTransactionsService } from './GetRecongizedTransactions';
import { GetRecognizedTransactionService } from './queries/GetRecognizedTransaction.service';
import { RevertRecognizedTransactionsService } from './commands/RevertRecognizedTransactions.service';
import { GetAutofillCategorizeTransactionService } from './queries/GetAutofillCategorizeTransaction.service';
import { IGetRecognizedTransactionsQuery } from '../BankingTransactions/types/BankingTransactions.types';
import { RevertRecognizedTransactionsCriteria } from './_types';
@Injectable()
export class RecognizedTransactionsApplication {
constructor(
private readonly getRecognizedTransactionsService: GetRecognizedTransactionsService,
private readonly getRecognizedTransactionService: GetRecognizedTransactionService,
private readonly revertRecognizedTransactionsService: RevertRecognizedTransactionsService,
private readonly getAutofillCategorizeTransactionService: GetAutofillCategorizeTransactionService,
) {}
/**
* Retrieves the recognized transactions based on the provided filter.
* @param {IGetRecognizedTransactionsQuery} filter - Filter criteria.
* @returns {Promise<{ data: any[], pagination: any }>}
*/
public getRecognizedTransactions(filter: IGetRecognizedTransactionsQuery) {
return this.getRecognizedTransactionsService.getRecognizedTranactions(
filter,
);
}
/**
* Retrieves a specific recognized transaction by ID.
* @param {number} recognizedTransactionId - The ID of the recognized transaction.
* @returns {Promise<any>}
*/
public getRecognizedTransaction(recognizedTransactionId: number) {
return this.getRecognizedTransactionService.getRecognizedTransaction(
recognizedTransactionId,
);
}
/**
* Reverts a recognized transaction.
* @param {number} ruleId - The ID of the recognized transaction to revert.
* @param {RevertRecognizedTransactionsCriteria} transactionsCriteria - The criteria for the recognized transaction to revert.
* @param {Knex.Transaction} trx - The transaction to use for the revert operation.
* @returns {Promise<any>}
*/
public revertRecognizedTransactions(
ruleId?: number | Array<number>,
transactionsCriteria?: RevertRecognizedTransactionsCriteria,
trx?: Knex.Transaction,
) {
return this.revertRecognizedTransactionsService.revertRecognizedTransactions(
ruleId,
transactionsCriteria,
trx,
);
}
/**
* Gets autofill categorize suggestions for a transaction.
* @param {number} uncategorizedTransactionId - The ID of the uncategorized transaction.
* @returns {Promise<any>}
*/
public getAutofillCategorizeTransaction(uncategorizedTransactionId: number) {
return this.getAutofillCategorizeTransactionService.getAutofillCategorizeTransaction(
uncategorizedTransactionId,
);
}
}

View File

@@ -1,7 +1,7 @@
import { Inject, Injectable } from '@nestjs/common';
import { GetRecognizedTransactionTransformer } from './GetRecognizedTransactionTransformer';
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
import { UncategorizedBankTransaction } from '../models/UncategorizedBankTransaction';
import { UncategorizedBankTransaction } from '../../BankingTransactions/models/UncategorizedBankTransaction';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
@Injectable()

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,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);

View File

@@ -11,13 +11,27 @@ import { ExcludeBankTransactionsApplication } from './ExcludeBankTransactionsApp
import { ExcludedBankTransactionsQuery } from './types/BankTransactionsExclude.types';
import { ApiOperation, ApiTags } from '@nestjs/swagger';
@Controller('banking/transactions')
@Controller('banking/exclude')
@ApiTags('banking-transactions')
export class BankingTransactionsExcludeController {
constructor(
private readonly excludeBankTransactionsApplication: ExcludeBankTransactionsApplication,
) {}
@Post('bulk')
@ApiOperation({ summary: 'Exclude the given bank transactions.' })
public excludeBankTransactions(@Body('ids') ids: number[]) {
return this.excludeBankTransactionsApplication.excludeBankTransactions(ids);
}
@Delete('bulk')
@ApiOperation({ summary: 'Unexclude the given bank transactions.' })
public unexcludeBankTransactions(@Body('ids') ids: number[]) {
return this.excludeBankTransactionsApplication.unexcludeBankTransactions(
ids,
);
}
@Get()
@ApiOperation({ summary: 'Retrieves the excluded bank transactions.' })
public getExcludedBankTransactions(
@@ -28,7 +42,7 @@ export class BankingTransactionsExcludeController {
);
}
@Post(':id/exclude')
@Post(':id')
@ApiOperation({ summary: 'Exclude the given bank transaction.' })
public excludeBankTransaction(@Param('id') id: string) {
return this.excludeBankTransactionsApplication.excludeBankTransaction(
@@ -36,25 +50,11 @@ export class BankingTransactionsExcludeController {
);
}
@Delete(':id/exclude')
@Delete(':id')
@ApiOperation({ summary: 'Unexclude the given bank transaction.' })
public unexcludeBankTransaction(@Param('id') id: string) {
return this.excludeBankTransactionsApplication.unexcludeBankTransaction(
Number(id),
);
}
@Post('bulk/exclude')
@ApiOperation({ summary: 'Exclude the given bank transactions.' })
public excludeBankTransactions(@Body('ids') ids: number[]) {
return this.excludeBankTransactionsApplication.excludeBankTransactions(ids);
}
@Delete('bulk/exclude')
@ApiOperation({ summary: 'Unexclude the given bank transactions.' })
public unexcludeBankTransactions(@Body('ids') ids: number[]) {
return this.excludeBankTransactionsApplication.unexcludeBankTransactions(
ids,
);
}
}

View File

@@ -1,4 +1,4 @@
import { Module } from '@nestjs/common';
import { forwardRef, Module } from '@nestjs/common';
import { ExcludeBankTransactionsApplication } from './ExcludeBankTransactionsApplication';
import { ExcludeBankTransactionService } from './commands/ExcludeBankTransaction.service';
import { UnexcludeBankTransactionService } from './commands/UnexcludeBankTransaction.service';
@@ -10,7 +10,9 @@ import { BankingTransactionsExcludeController } from './BankingTransactionsExclu
import { BankingTransactionsModule } from '../BankingTransactions/BankingTransactions.module';
@Module({
imports: [BankingTransactionsModule],
imports: [
forwardRef(() => BankingTransactionsModule),
],
providers: [
ExcludeBankTransactionsApplication,
ExcludeBankTransactionService,