mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-19 22:30:31 +00:00
refactor(nestjs): banking modules
This commit is contained in:
@@ -90,6 +90,8 @@ import { MiscellaneousModule } from '../Miscellaneous/Miscellaneous.module';
|
|||||||
import { UsersModule } from '../UsersModule/Users.module';
|
import { UsersModule } from '../UsersModule/Users.module';
|
||||||
import { ContactsModule } from '../Contacts/Contacts.module';
|
import { ContactsModule } from '../Contacts/Contacts.module';
|
||||||
import { BankingPlaidModule } from '../BankingPlaid/BankingPlaid.module';
|
import { BankingPlaidModule } from '../BankingPlaid/BankingPlaid.module';
|
||||||
|
import { BankingCategorizeModule } from '../BankingCategorize/BankingCategorize.module';
|
||||||
|
import { TenantModelsInitializeModule } from '../Tenancy/TenantModelsInitialize.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -151,6 +153,7 @@ import { BankingPlaidModule } from '../BankingPlaid/BankingPlaid.module';
|
|||||||
ScheduleModule.forRoot(),
|
ScheduleModule.forRoot(),
|
||||||
TenancyDatabaseModule,
|
TenancyDatabaseModule,
|
||||||
TenancyModelsModule,
|
TenancyModelsModule,
|
||||||
|
TenantModelsInitializeModule,
|
||||||
AuthModule,
|
AuthModule,
|
||||||
TenancyModule,
|
TenancyModule,
|
||||||
ChromiumlyTenancyModule,
|
ChromiumlyTenancyModule,
|
||||||
@@ -188,6 +191,7 @@ import { BankingPlaidModule } from '../BankingPlaid/BankingPlaid.module';
|
|||||||
BankingTransactionsModule,
|
BankingTransactionsModule,
|
||||||
BankingMatchingModule,
|
BankingMatchingModule,
|
||||||
BankingPlaidModule,
|
BankingPlaidModule,
|
||||||
|
BankingCategorizeModule,
|
||||||
TransactionsLockingModule,
|
TransactionsLockingModule,
|
||||||
SettingsModule,
|
SettingsModule,
|
||||||
FeaturesModule,
|
FeaturesModule,
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
import { Knex } from 'knex';
|
||||||
|
import { CategorizeBankTransaction } from './commands/CategorizeBankTransaction';
|
||||||
|
import { UncategorizeBankTransactionService } from './commands/UncategorizeBankTransaction.service';
|
||||||
|
import { UncategorizeBankTransactionsBulk } from './commands/UncategorizeBankTransactionsBulk.service';
|
||||||
|
import { UncategorizedBankTransactionDto } from './dtos/CreateUncategorizedBankTransaction.dto';
|
||||||
|
import { CategorizeBankTransactionDto } from './dtos/CategorizeBankTransaction.dto';
|
||||||
|
import { CategorizeTransactionAsExpense } from './commands/CategorizeTransactionAsExpense';
|
||||||
|
import { CreateUncategorizedTransactionService } from './commands/CreateUncategorizedTransaction.service';
|
||||||
|
import { ICategorizeCashflowTransactioDTO } from './types/BankingCategorize.types';
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class BankingCategorizeApplication {
|
||||||
|
constructor(
|
||||||
|
private readonly categorizeBankTransaction: CategorizeBankTransaction,
|
||||||
|
private readonly uncategorizeBankTransaction: UncategorizeBankTransactionService,
|
||||||
|
private readonly uncategorizeBankTransactionsBulk: UncategorizeBankTransactionsBulk,
|
||||||
|
private readonly categorizeTransactionAsExpense: CategorizeTransactionAsExpense,
|
||||||
|
private readonly createUncategorizedTransaction: CreateUncategorizedTransactionService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Categorize a bank transaction with the given ID and categorization data.
|
||||||
|
* @param {number | Array<number>} uncategorizedTransactionId - The ID(s) of the uncategorized transaction(s) to categorize.
|
||||||
|
* @param {CategorizeBankTransactionDto} categorizeDTO - Data for categorization.
|
||||||
|
* @returns {Promise<any>} The result of the categorization operation.
|
||||||
|
*/
|
||||||
|
public categorizeTransaction(
|
||||||
|
uncategorizedTransactionId: number | Array<number>,
|
||||||
|
categorizeDTO: CategorizeBankTransactionDto,
|
||||||
|
) {
|
||||||
|
return this.categorizeBankTransaction.categorize(
|
||||||
|
uncategorizedTransactionId,
|
||||||
|
categorizeDTO,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uncategorize a bank transaction with the given ID.
|
||||||
|
* @param {number} uncategorizedTransactionId - The ID of the transaction to uncategorize.
|
||||||
|
* @returns {Promise<Array<number>>} Array of affected transaction IDs.
|
||||||
|
*/
|
||||||
|
public uncategorizeTransaction(
|
||||||
|
uncategorizedTransactionId: number,
|
||||||
|
): Promise<Array<number>> {
|
||||||
|
return this.uncategorizeBankTransaction.uncategorize(
|
||||||
|
uncategorizedTransactionId,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uncategorize multiple bank transactions in bulk.
|
||||||
|
* @param {number | Array<number>} uncategorizedTransactionIds - The ID(s) of the transaction(s) to uncategorize.
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
public uncategorizeTransactionsBulk(
|
||||||
|
uncategorizedTransactionIds: number | Array<number>,
|
||||||
|
) {
|
||||||
|
return this.uncategorizeBankTransactionsBulk.uncategorizeBulk(
|
||||||
|
uncategorizedTransactionIds,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Categorize a transaction as an expense.
|
||||||
|
* @param {number} cashflowTransactionId - The ID of the cashflow transaction to categorize.
|
||||||
|
* @param {ICategorizeCashflowTransactioDTO} transactionDTO - Data for categorization.
|
||||||
|
* @returns {Promise<any>} The result of the categorization operation.
|
||||||
|
*/
|
||||||
|
public categorizeTransactionAsExpenseType(
|
||||||
|
cashflowTransactionId: number,
|
||||||
|
transactionDTO: ICategorizeCashflowTransactioDTO,
|
||||||
|
) {
|
||||||
|
return this.categorizeTransactionAsExpense.categorize(
|
||||||
|
cashflowTransactionId,
|
||||||
|
transactionDTO,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new uncategorized bank transaction.
|
||||||
|
* @param {UncategorizedBankTransactionDto} createDTO - Data for creating the uncategorized transaction.
|
||||||
|
* @param {Knex.Transaction} [trx] - Optional Knex transaction.
|
||||||
|
* @returns {Promise<any>} The created uncategorized transaction.
|
||||||
|
*/
|
||||||
|
public createUncategorizedBankTransaction(
|
||||||
|
createDTO: UncategorizedBankTransactionDto,
|
||||||
|
trx?: Knex.Transaction,
|
||||||
|
) {
|
||||||
|
return this.createUncategorizedTransaction.create(createDTO, trx);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import { Body, Controller, Delete, Param, Post, Query } from '@nestjs/common';
|
||||||
|
import { castArray, omit } from 'lodash';
|
||||||
|
import { BankingCategorizeApplication } from './BankingCategorize.application';
|
||||||
|
import { CategorizeBankTransactionRouteDto } from './dtos/CategorizeBankTransaction.dto';
|
||||||
|
|
||||||
|
@Controller('banking/categorize')
|
||||||
|
export class BankingCategorizeController {
|
||||||
|
constructor(
|
||||||
|
private readonly bankingCategorizeApplication: BankingCategorizeApplication,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
@Post()
|
||||||
|
public categorizeTransaction(
|
||||||
|
@Body() body: CategorizeBankTransactionRouteDto,
|
||||||
|
) {
|
||||||
|
return this.bankingCategorizeApplication.categorizeTransaction(
|
||||||
|
castArray(body.uncategorizedTransactionIds),
|
||||||
|
omit(body, 'uncategorizedTransactionIds'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Delete('/bulk')
|
||||||
|
public uncategorizeTransactionsBulk(
|
||||||
|
@Query() uncategorizedTransactionIds: number[] | number,
|
||||||
|
) {
|
||||||
|
return this.bankingCategorizeApplication.uncategorizeTransactionsBulk(
|
||||||
|
castArray(uncategorizedTransactionIds),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Delete('/:id')
|
||||||
|
public uncategorizeTransaction(
|
||||||
|
@Param('id') uncategorizedTransactionId: number,
|
||||||
|
) {
|
||||||
|
return this.bankingCategorizeApplication.uncategorizeTransaction(
|
||||||
|
Number(uncategorizedTransactionId),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,20 +1,38 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { forwardRef, Module } from '@nestjs/common';
|
||||||
import { CreateUncategorizedTransactionService } from './commands/CreateUncategorizedTransaction.service';
|
import { CreateUncategorizedTransactionService } from './commands/CreateUncategorizedTransaction.service';
|
||||||
import { CategorizeTransactionAsExpense } from './commands/CategorizeTransactionAsExpense';
|
import { CategorizeTransactionAsExpense } from './commands/CategorizeTransactionAsExpense';
|
||||||
import { BankingTransactionsModule } from '../BankingTransactions/BankingTransactions.module';
|
import { BankingTransactionsModule } from '../BankingTransactions/BankingTransactions.module';
|
||||||
import { ExpensesModule } from '../Expenses/Expenses.module';
|
import { ExpensesModule } from '../Expenses/Expenses.module';
|
||||||
import { UncategorizedTransactionsImportable } from './commands/UncategorizedTransactionsImportable';
|
import { UncategorizedTransactionsImportable } from './commands/UncategorizedTransactionsImportable';
|
||||||
|
import { BankingCategorizeController } from './BankingCategorize.controller';
|
||||||
|
import { BankingCategorizeApplication } from './BankingCategorize.application';
|
||||||
|
import { CategorizeBankTransaction } from './commands/CategorizeBankTransaction';
|
||||||
|
import { UncategorizeBankTransactionService } from './commands/UncategorizeBankTransaction.service';
|
||||||
|
import { UncategorizeBankTransactionsBulk } from './commands/UncategorizeBankTransactionsBulk.service';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [BankingTransactionsModule, ExpensesModule],
|
imports: [
|
||||||
|
BankingTransactionsModule,
|
||||||
|
ExpensesModule,
|
||||||
|
forwardRef(() => BankingTransactionsModule),
|
||||||
|
],
|
||||||
providers: [
|
providers: [
|
||||||
CreateUncategorizedTransactionService,
|
CreateUncategorizedTransactionService,
|
||||||
CategorizeTransactionAsExpense,
|
CategorizeTransactionAsExpense,
|
||||||
UncategorizedTransactionsImportable
|
UncategorizedTransactionsImportable,
|
||||||
|
BankingCategorizeApplication,
|
||||||
|
CategorizeBankTransaction,
|
||||||
|
UncategorizeBankTransactionService,
|
||||||
|
UncategorizeBankTransactionsBulk,
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
CreateUncategorizedTransactionService,
|
CreateUncategorizedTransactionService,
|
||||||
CategorizeTransactionAsExpense,
|
CategorizeTransactionAsExpense,
|
||||||
|
BankingCategorizeApplication,
|
||||||
|
CategorizeBankTransaction,
|
||||||
|
UncategorizeBankTransactionService,
|
||||||
|
UncategorizeBankTransactionsBulk,
|
||||||
],
|
],
|
||||||
|
controllers: [BankingCategorizeController],
|
||||||
})
|
})
|
||||||
export class BankingCategorizeModule {}
|
export class BankingCategorizeModule {}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import { Knex } from 'knex';
|
|||||||
import {
|
import {
|
||||||
ICashflowTransactionCategorizedPayload,
|
ICashflowTransactionCategorizedPayload,
|
||||||
ICashflowTransactionUncategorizingPayload,
|
ICashflowTransactionUncategorizingPayload,
|
||||||
ICategorizeCashflowTransactioDTO,
|
|
||||||
} from '../types/BankingCategorize.types';
|
} from '../types/BankingCategorize.types';
|
||||||
import {
|
import {
|
||||||
transformCategorizeTransToCashflow,
|
transformCategorizeTransToCashflow,
|
||||||
@@ -17,9 +16,10 @@ import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
|
|||||||
import { UncategorizedBankTransaction } from '@/modules/BankingTransactions/models/UncategorizedBankTransaction';
|
import { UncategorizedBankTransaction } from '@/modules/BankingTransactions/models/UncategorizedBankTransaction';
|
||||||
import { events } from '@/common/events/events';
|
import { events } from '@/common/events/events';
|
||||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||||
|
import { CategorizeBankTransactionDto } from '../dtos/CategorizeBankTransaction.dto';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CategorizeCashflowTransaction {
|
export class CategorizeBankTransaction {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly eventPublisher: EventEmitter2,
|
private readonly eventPublisher: EventEmitter2,
|
||||||
private readonly uow: UnitOfWork,
|
private readonly uow: UnitOfWork,
|
||||||
@@ -38,7 +38,7 @@ export class CategorizeCashflowTransaction {
|
|||||||
*/
|
*/
|
||||||
public async categorize(
|
public async categorize(
|
||||||
uncategorizedTransactionId: number | Array<number>,
|
uncategorizedTransactionId: number | Array<number>,
|
||||||
categorizeDTO: ICategorizeCashflowTransactioDTO,
|
categorizeDTO: CategorizeBankTransactionDto,
|
||||||
) {
|
) {
|
||||||
const uncategorizedTransactionIds = castArray(uncategorizedTransactionId);
|
const uncategorizedTransactionIds = castArray(uncategorizedTransactionId);
|
||||||
|
|
||||||
@@ -68,7 +68,6 @@ export class CategorizeCashflowTransaction {
|
|||||||
await this.eventPublisher.emitAsync(
|
await this.eventPublisher.emitAsync(
|
||||||
events.cashflow.onTransactionCategorizing,
|
events.cashflow.onTransactionCategorizing,
|
||||||
{
|
{
|
||||||
// tenantId,
|
|
||||||
oldUncategorizedTransactions,
|
oldUncategorizedTransactions,
|
||||||
trx,
|
trx,
|
||||||
} as ICashflowTransactionUncategorizingPayload,
|
} as ICashflowTransactionUncategorizingPayload,
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
import { Knex } from 'knex';
|
import { Knex } from 'knex';
|
||||||
import {
|
import {
|
||||||
CreateUncategorizedTransactionDTO,
|
|
||||||
IUncategorizedTransactionCreatedEventPayload,
|
IUncategorizedTransactionCreatedEventPayload,
|
||||||
IUncategorizedTransactionCreatingEventPayload,
|
IUncategorizedTransactionCreatingEventPayload,
|
||||||
} from '../types/BankingCategorize.types';
|
} from '../types/BankingCategorize.types';
|
||||||
@@ -10,6 +9,7 @@ import { UncategorizedBankTransaction } from '../../BankingTransactions/models/U
|
|||||||
import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
|
import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
|
||||||
import { events } from '@/common/events/events';
|
import { events } from '@/common/events/events';
|
||||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||||
|
import { UncategorizedBankTransactionDto } from '../dtos/CreateUncategorizedBankTransaction.dto';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CreateUncategorizedTransactionService {
|
export class CreateUncategorizedTransactionService {
|
||||||
@@ -30,7 +30,7 @@ export class CreateUncategorizedTransactionService {
|
|||||||
* @returns {Promise<UncategorizedBankTransaction>}
|
* @returns {Promise<UncategorizedBankTransaction>}
|
||||||
*/
|
*/
|
||||||
public create(
|
public create(
|
||||||
createUncategorizedTransactionDTO: CreateUncategorizedTransactionDTO,
|
createUncategorizedTransactionDTO: UncategorizedBankTransactionDto,
|
||||||
trx?: Knex.Transaction,
|
trx?: Knex.Transaction,
|
||||||
) {
|
) {
|
||||||
return this.uow.withTransaction(async (trx: Knex.Transaction) => {
|
return this.uow.withTransaction(async (trx: Knex.Transaction) => {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { UncategorizedBankTransaction } from '../../BankingTransactions/models/U
|
|||||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class UncategorizeCashflowTransactionService {
|
export class UncategorizeBankTransactionService {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly eventPublisher: EventEmitter2,
|
private readonly eventPublisher: EventEmitter2,
|
||||||
private readonly uow: UnitOfWork,
|
private readonly uow: UnitOfWork,
|
||||||
@@ -1,18 +1,17 @@
|
|||||||
import { castArray } from 'lodash';
|
import { castArray } from 'lodash';
|
||||||
import { PromisePool } from '@supercharge/promise-pool';
|
import { PromisePool } from '@supercharge/promise-pool';
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { UncategorizeCashflowTransactionService } from './UncategorizeCashflowTransaction.service';
|
import { UncategorizeBankTransactionService } from './UncategorizeBankTransaction.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class UncategorizeCashflowTransactionsBulk {
|
export class UncategorizeBankTransactionsBulk {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly uncategorizeTransactionService: UncategorizeCashflowTransactionService
|
private readonly uncategorizeTransactionService: UncategorizeBankTransactionService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uncategorize the given bank transactions in bulk.
|
* Uncategorize the given bank transactions in bulk.
|
||||||
* @param {number} tenantId
|
* @param {number | Array<number>} uncategorizedTransactionId
|
||||||
* @param {number} uncategorizedTransactionId
|
|
||||||
*/
|
*/
|
||||||
public async uncategorizeBulk(
|
public async uncategorizeBulk(
|
||||||
uncategorizedTransactionId: number | Array<number>
|
uncategorizedTransactionId: number | Array<number>
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
import { ToNumber } from '@/common/decorators/Validators';
|
||||||
|
import {
|
||||||
|
IsArray,
|
||||||
|
IsDateString,
|
||||||
|
IsInt,
|
||||||
|
IsNotEmpty,
|
||||||
|
IsNumber,
|
||||||
|
IsOptional,
|
||||||
|
IsString,
|
||||||
|
} from 'class-validator';
|
||||||
|
|
||||||
|
export class CategorizeBankTransactionDto {
|
||||||
|
@IsDateString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
date: Date;
|
||||||
|
|
||||||
|
@IsInt()
|
||||||
|
@ToNumber()
|
||||||
|
@IsNotEmpty()
|
||||||
|
creditAccountId: number;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
referenceNo: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
transactionNumber: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
transactionType: string;
|
||||||
|
|
||||||
|
@IsNumber()
|
||||||
|
@ToNumber()
|
||||||
|
@IsOptional()
|
||||||
|
exchangeRate: number = 1;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
currencyCode: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
description: string;
|
||||||
|
|
||||||
|
@IsNumber()
|
||||||
|
@IsOptional()
|
||||||
|
branchId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class CategorizeBankTransactionRouteDto extends CategorizeBankTransactionDto {
|
||||||
|
@IsArray()
|
||||||
|
uncategorizedTransactionIds: Array<number>;
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import { IsBoolean, IsDateString, IsNumber, IsString } from 'class-validator';
|
||||||
|
|
||||||
|
export class UncategorizedBankTransactionDto {
|
||||||
|
@IsDateString()
|
||||||
|
date: Date | string;
|
||||||
|
|
||||||
|
@IsNumber()
|
||||||
|
accountId: number;
|
||||||
|
|
||||||
|
@IsNumber()
|
||||||
|
amount: number;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
currencyCode: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
payee?: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
description?: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
referenceNo?: string | null;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
plaidTransactionId?: string | null;
|
||||||
|
|
||||||
|
@IsBoolean()
|
||||||
|
pending?: boolean;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
pendingPlaidTransactionId?: string | null;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
batch?: string;
|
||||||
|
}
|
||||||
@@ -1,47 +1,48 @@
|
|||||||
import { ApiOperation, ApiTags } from '@nestjs/swagger';
|
import { ApiOperation, ApiTags } from '@nestjs/swagger';
|
||||||
import { Body, Controller, Get, Param, Post, Query } from '@nestjs/common';
|
import { Body, Controller, Get, Param, Post, Query } from '@nestjs/common';
|
||||||
import { BankingMatchingApplication } from './BankingMatchingApplication';
|
import { BankingMatchingApplication } from './BankingMatchingApplication';
|
||||||
import { GetMatchedTransactionsFilter, IMatchTransactionDTO } from './types';
|
import { GetMatchedTransactionsFilter } from './types';
|
||||||
import { MatchBankTransactionDto } from './dtos/MatchBankTransaction.dto';
|
import { MatchBankTransactionDto } from './dtos/MatchBankTransaction.dto';
|
||||||
|
|
||||||
@Controller('banking/matching')
|
@Controller('banking/matching')
|
||||||
@ApiTags('banking-transactions-matching')
|
@ApiTags('banking-transactions-matching')
|
||||||
export class BankingMatchingController {
|
export class BankingMatchingController {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly bankingMatchingApplication: BankingMatchingApplication
|
private readonly bankingMatchingApplication: BankingMatchingApplication,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@Get('matched')
|
@Get('matched')
|
||||||
@ApiOperation({ summary: 'Retrieves the matched transactions.' })
|
@ApiOperation({ summary: 'Retrieves the matched transactions.' })
|
||||||
async getMatchedTransactions(
|
async getMatchedTransactions(
|
||||||
@Query('uncategorizedTransactionIds') uncategorizedTransactionIds: number[],
|
@Query('uncategorizedTransactionIds') uncategorizedTransactionIds: number[],
|
||||||
@Query() filter: GetMatchedTransactionsFilter
|
@Query() filter: GetMatchedTransactionsFilter,
|
||||||
) {
|
) {
|
||||||
return this.bankingMatchingApplication.getMatchedTransactions(
|
return this.bankingMatchingApplication.getMatchedTransactions(
|
||||||
uncategorizedTransactionIds,
|
uncategorizedTransactionIds,
|
||||||
filter
|
filter,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('/match/:uncategorizedTransactionId')
|
@Post('/match/:uncategorizedTransactionId')
|
||||||
@ApiOperation({ summary: 'Match the given uncategorized transaction.' })
|
@ApiOperation({ summary: 'Match the given uncategorized transaction.' })
|
||||||
async matchTransaction(
|
async matchTransaction(
|
||||||
@Param('uncategorizedTransactionId') uncategorizedTransactionId: number | number[],
|
@Param('uncategorizedTransactionId')
|
||||||
@Body() matchedTransactions: MatchBankTransactionDto
|
uncategorizedTransactionId: number | number[],
|
||||||
|
@Body() matchedTransactions: MatchBankTransactionDto,
|
||||||
) {
|
) {
|
||||||
return this.bankingMatchingApplication.matchTransaction(
|
return this.bankingMatchingApplication.matchTransaction(
|
||||||
uncategorizedTransactionId,
|
uncategorizedTransactionId,
|
||||||
matchedTransactions
|
matchedTransactions,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('/unmatch/:uncategorizedTransactionId')
|
@Post('/unmatch/:uncategorizedTransactionId')
|
||||||
@ApiOperation({ summary: 'Unmatch the given uncategorized transaction.' })
|
@ApiOperation({ summary: 'Unmatch the given uncategorized transaction.' })
|
||||||
async unmatchMatchedTransaction(
|
async unmatchMatchedTransaction(
|
||||||
@Param('uncategorizedTransactionId') uncategorizedTransactionId: number
|
@Param('uncategorizedTransactionId') uncategorizedTransactionId: number,
|
||||||
) {
|
) {
|
||||||
return this.bankingMatchingApplication.unmatchMatchedTransaction(
|
return this.bankingMatchingApplication.unmatchMatchedTransaction(
|
||||||
uncategorizedTransactionId
|
uncategorizedTransactionId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { Knex } from 'knex';
|
||||||
import { GetMatchedTransactionsByType } from './GetMatchedTransactionsByType';
|
import { GetMatchedTransactionsByType } from './GetMatchedTransactionsByType';
|
||||||
import { GetMatchedTransactionCashflowTransformer } from './GetMatchedTransactionCashflowTransformer';
|
import { GetMatchedTransactionCashflowTransformer } from './GetMatchedTransactionCashflowTransformer';
|
||||||
import { GetMatchedTransactionsFilter } from '../types';
|
import { GetMatchedTransactionsFilter } from '../types';
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { GetMatchedTransactionsFilter, MatchedTransactionPOJO } from '../types';
|
import { GetMatchedTransactionsFilter, MatchedTransactionPOJO, MatchedTransactionsPOJO } from '../types';
|
||||||
import { GetMatchedTransactionsByType } from './GetMatchedTransactionsByType';
|
import { GetMatchedTransactionsByType } from './GetMatchedTransactionsByType';
|
||||||
import { GetMatchedTransactionExpensesTransformer } from './GetMatchedTransactionExpensesTransformer';
|
import { GetMatchedTransactionExpensesTransformer } from './GetMatchedTransactionExpensesTransformer';
|
||||||
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
|
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
|
||||||
import { Expense } from '@/modules/Expenses/models/Expense.model';
|
import { Expense } from '@/modules/Expenses/models/Expense.model';
|
||||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||||
|
import { Knex } from 'knex';
|
||||||
|
import { TENANCY_DB_CONNECTION } from '@/modules/Tenancy/TenancyDB/TenancyDB.constants';
|
||||||
|
import { initialize } from 'objection';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class GetMatchedTransactionsByExpenses extends GetMatchedTransactionsByType {
|
export class GetMatchedTransactionsByExpenses extends GetMatchedTransactionsByType {
|
||||||
@@ -13,17 +16,26 @@ export class GetMatchedTransactionsByExpenses extends GetMatchedTransactionsByTy
|
|||||||
|
|
||||||
@Inject(Expense.name)
|
@Inject(Expense.name)
|
||||||
protected readonly expenseModel: TenantModelProxy<typeof Expense>,
|
protected readonly expenseModel: TenantModelProxy<typeof Expense>,
|
||||||
|
|
||||||
|
@Inject(TENANCY_DB_CONNECTION)
|
||||||
|
private readonly tenantDb: () => Knex,
|
||||||
|
|
||||||
|
@Inject('TENANT_MODELS_INIT')
|
||||||
|
private readonly tenantModelsInit: () => Promise<boolean>,
|
||||||
|
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the matched transactions of expenses.
|
* Retrieves the matched transactions of expenses.
|
||||||
* @param {number} tenantId
|
|
||||||
* @param {GetMatchedTransactionsFilter} filter
|
* @param {GetMatchedTransactionsFilter} filter
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
async getMatchedTransactions(filter: GetMatchedTransactionsFilter) {
|
async getMatchedTransactions(
|
||||||
|
filter: GetMatchedTransactionsFilter,
|
||||||
|
): Promise<MatchedTransactionsPOJO> {
|
||||||
|
// await this.tenantModelsInit();
|
||||||
// Retrieve the expense matches.
|
// Retrieve the expense matches.
|
||||||
const expenses = await this.expenseModel()
|
const expenses = await this.expenseModel()
|
||||||
.query()
|
.query()
|
||||||
@@ -49,6 +61,7 @@ export class GetMatchedTransactionsByExpenses extends GetMatchedTransactionsByTy
|
|||||||
}
|
}
|
||||||
query.orderBy('paymentDate', 'DESC');
|
query.orderBy('paymentDate', 'DESC');
|
||||||
});
|
});
|
||||||
|
|
||||||
return this.transformer.transform(
|
return this.transformer.transform(
|
||||||
expenses,
|
expenses,
|
||||||
new GetMatchedTransactionExpensesTransformer(),
|
new GetMatchedTransactionExpensesTransformer(),
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { Knex } from 'knex';
|
import { Knex } from 'knex';
|
||||||
import { first } from 'lodash';
|
import { first } from 'lodash';
|
||||||
import { GetMatchedTransactionInvoicesTransformer } from './GetMatchedTransactionInvoicesTransformer';
|
import { GetMatchedTransactionInvoicesTransformer } from './GetMatchedTransactionInvoicesTransformer';
|
||||||
@@ -9,7 +10,6 @@ import {
|
|||||||
} from '../types';
|
} from '../types';
|
||||||
import { GetMatchedTransactionsByType } from './GetMatchedTransactionsByType';
|
import { GetMatchedTransactionsByType } from './GetMatchedTransactionsByType';
|
||||||
import { CreatePaymentReceivedService } from '@/modules/PaymentReceived/commands/CreatePaymentReceived.serivce';
|
import { CreatePaymentReceivedService } from '@/modules/PaymentReceived/commands/CreatePaymentReceived.serivce';
|
||||||
import { Inject, Injectable } from '@nestjs/common';
|
|
||||||
import { SaleInvoice } from '@/modules/SaleInvoices/models/SaleInvoice';
|
import { SaleInvoice } from '@/modules/SaleInvoices/models/SaleInvoice';
|
||||||
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
|
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
|
||||||
import { UncategorizedBankTransaction } from '@/modules/BankingTransactions/models/UncategorizedBankTransaction';
|
import { UncategorizedBankTransaction } from '@/modules/BankingTransactions/models/UncategorizedBankTransaction';
|
||||||
@@ -86,7 +86,6 @@ export class GetMatchedTransactionsByInvoices extends GetMatchedTransactionsByTy
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the common matched transaction.
|
* Creates the common matched transaction.
|
||||||
* @param {number} tenantId
|
|
||||||
* @param {Array<number>} uncategorizedTransactionIds
|
* @param {Array<number>} uncategorizedTransactionIds
|
||||||
* @param {IMatchTransactionDTO} matchTransactionDTO
|
* @param {IMatchTransactionDTO} matchTransactionDTO
|
||||||
* @param {Knex.Transaction} trx
|
* @param {Knex.Transaction} trx
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
|
import { Knex } from 'knex';
|
||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
|
import { initialize } from 'objection';
|
||||||
import { GetMatchedTransactionManualJournalsTransformer } from './GetMatchedTransactionManualJournalsTransformer';
|
import { GetMatchedTransactionManualJournalsTransformer } from './GetMatchedTransactionManualJournalsTransformer';
|
||||||
import { GetMatchedTransactionsByType } from './GetMatchedTransactionsByType';
|
import { GetMatchedTransactionsByType } from './GetMatchedTransactionsByType';
|
||||||
import { GetMatchedTransactionsFilter } from '../types';
|
import { GetMatchedTransactionsFilter } from '../types';
|
||||||
import { ManualJournal } from '@/modules/ManualJournals/models/ManualJournal';
|
import { ManualJournal } from '@/modules/ManualJournals/models/ManualJournal';
|
||||||
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
|
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
|
||||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||||
|
import { TENANCY_DB_CONNECTION } from '@/modules/Tenancy/TenancyDB/TenancyDB.constants';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class GetMatchedTransactionsByManualJournals extends GetMatchedTransactionsByType {
|
export class GetMatchedTransactionsByManualJournals extends GetMatchedTransactionsByType {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
|||||||
|
|
||||||
export abstract class GetMatchedTransactionsByType {
|
export abstract class GetMatchedTransactionsByType {
|
||||||
@Inject(MatchedBankTransaction.name)
|
@Inject(MatchedBankTransaction.name)
|
||||||
private readonly matchedBankTransactionModel: TenantModelProxy<
|
matchedBankTransactionModel: TenantModelProxy<
|
||||||
typeof MatchedBankTransaction
|
typeof MatchedBankTransaction
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
|||||||
@@ -76,6 +76,11 @@ const models = [
|
|||||||
GetPendingBankAccountTransactions,
|
GetPendingBankAccountTransactions,
|
||||||
GetAutofillCategorizeTransactionService,
|
GetAutofillCategorizeTransactionService,
|
||||||
],
|
],
|
||||||
exports: [...models, RemovePendingUncategorizedTransaction],
|
exports: [
|
||||||
|
...models,
|
||||||
|
RemovePendingUncategorizedTransaction,
|
||||||
|
CommandBankTransactionValidator,
|
||||||
|
CreateBankTransactionService
|
||||||
|
],
|
||||||
})
|
})
|
||||||
export class BankingTransactionsModule {}
|
export class BankingTransactionsModule {}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import { GetUncategorizedTransactionsQueryDto } from './dtos/GetUncategorizedTra
|
|||||||
import { GetPendingBankAccountTransactions } from './queries/GetPendingBankAccountTransaction.service';
|
import { GetPendingBankAccountTransactions } from './queries/GetPendingBankAccountTransaction.service';
|
||||||
import { GetPendingTransactionsQueryDto } from './dtos/GetPendingTransactionsQuery.dto';
|
import { GetPendingTransactionsQueryDto } from './dtos/GetPendingTransactionsQuery.dto';
|
||||||
import { GetAutofillCategorizeTransactionService } from './queries/GetAutofillCategorizeTransaction/GetAutofillCategorizeTransaction.service';
|
import { GetAutofillCategorizeTransactionService } from './queries/GetAutofillCategorizeTransaction/GetAutofillCategorizeTransaction.service';
|
||||||
|
import { GetBankTransactionsQueryDto } from './dtos/GetBankTranasctionsQuery.dto';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class BankingTransactionsApplication {
|
export class BankingTransactionsApplication {
|
||||||
@@ -54,7 +55,7 @@ export class BankingTransactionsApplication {
|
|||||||
* Retrieves the bank transactions of the given bank id.
|
* Retrieves the bank transactions of the given bank id.
|
||||||
* @param {ICashflowAccountTransactionsQuery} query
|
* @param {ICashflowAccountTransactionsQuery} query
|
||||||
*/
|
*/
|
||||||
public getBankAccountTransactions(query: ICashflowAccountTransactionsQuery) {
|
public getBankAccountTransactions(query: GetBankTransactionsQueryDto) {
|
||||||
return this.getBankAccountTransactionsService.bankAccountTransactions(
|
return this.getBankAccountTransactionsService.bankAccountTransactions(
|
||||||
query,
|
query,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
import { includes, camelCase, upperFirst, sumBy } from 'lodash';
|
import { includes, camelCase, upperFirst, sumBy } from 'lodash';
|
||||||
import { getCashflowTransactionType } from '../utils';
|
import { getCashflowTransactionType } from '../utils';
|
||||||
import {
|
import {
|
||||||
@@ -6,7 +7,6 @@ import {
|
|||||||
ERRORS,
|
ERRORS,
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
import { Account } from '@/modules/Accounts/models/Account.model';
|
import { Account } from '@/modules/Accounts/models/Account.model';
|
||||||
import { Injectable } from '@nestjs/common';
|
|
||||||
import { ServiceError } from '@/modules/Items/ServiceError';
|
import { ServiceError } from '@/modules/Items/ServiceError';
|
||||||
import { BankTransaction } from '../models/BankTransaction';
|
import { BankTransaction } from '../models/BankTransaction';
|
||||||
import { UncategorizedBankTransaction } from '../models/UncategorizedBankTransaction';
|
import { UncategorizedBankTransaction } from '../models/UncategorizedBankTransaction';
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { pick } from 'lodash';
|
import { pick } from 'lodash';
|
||||||
import { Knex } from 'knex';
|
import { Knex } from 'knex';
|
||||||
import * as R from 'ramda';
|
|
||||||
import * as composeAsync from 'async/compose';
|
import * as composeAsync from 'async/compose';
|
||||||
import { CASHFLOW_TRANSACTION_TYPE } from '../constants';
|
import { CASHFLOW_TRANSACTION_TYPE } from '../constants';
|
||||||
import { transformCashflowTransactionType } from '../utils';
|
import { transformCashflowTransactionType } from '../utils';
|
||||||
@@ -14,12 +13,12 @@ import { events } from '@/common/events/events';
|
|||||||
import { Account } from '@/modules/Accounts/models/Account.model';
|
import { Account } from '@/modules/Accounts/models/Account.model';
|
||||||
import { BankTransaction } from '../models/BankTransaction';
|
import { BankTransaction } from '../models/BankTransaction';
|
||||||
import {
|
import {
|
||||||
ICashflowNewCommandDTO,
|
|
||||||
ICommandCashflowCreatedPayload,
|
ICommandCashflowCreatedPayload,
|
||||||
ICommandCashflowCreatingPayload,
|
ICommandCashflowCreatingPayload,
|
||||||
} from '../types/BankingTransactions.types';
|
} from '../types/BankingTransactions.types';
|
||||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||||
import { CreateBankTransactionDto } from '../dtos/CreateBankTransaction.dto';
|
import { CreateBankTransactionDto } from '../dtos/CreateBankTransaction.dto';
|
||||||
|
import { formatDateFields } from '@/utils/format-date-fields';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CreateBankTransactionService {
|
export class CreateBankTransactionService {
|
||||||
@@ -42,7 +41,7 @@ export class CreateBankTransactionService {
|
|||||||
* @param {ICashflowNewCommandDTO} newCashflowTransactionDTO
|
* @param {ICashflowNewCommandDTO} newCashflowTransactionDTO
|
||||||
*/
|
*/
|
||||||
public authorize = async (
|
public authorize = async (
|
||||||
newCashflowTransactionDTO: ICashflowNewCommandDTO,
|
newCashflowTransactionDTO: CreateBankTransactionDto,
|
||||||
creditAccount: Account,
|
creditAccount: Account,
|
||||||
) => {
|
) => {
|
||||||
const transactionType = transformCashflowTransactionType(
|
const transactionType = transformCashflowTransactionType(
|
||||||
@@ -60,7 +59,7 @@ export class CreateBankTransactionService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Transformes owner contribution DTO to cashflow transaction.
|
* Transformes owner contribution DTO to cashflow transaction.
|
||||||
* @param {ICashflowNewCommandDTO} newCashflowTransactionDTO - New transaction DTO.
|
* @param {CreateBankTransactionDto} newCashflowTransactionDTO - New transaction DTO.
|
||||||
* @returns {ICashflowTransactionInput} - Cashflow transaction object.
|
* @returns {ICashflowTransactionInput} - Cashflow transaction object.
|
||||||
*/
|
*/
|
||||||
private transformCashflowTransactionDTO = async (
|
private transformCashflowTransactionDTO = async (
|
||||||
@@ -91,7 +90,7 @@ export class CreateBankTransactionService {
|
|||||||
|
|
||||||
const initialDTO = {
|
const initialDTO = {
|
||||||
amount,
|
amount,
|
||||||
...fromDTO,
|
...formatDateFields(fromDTO, ['date']),
|
||||||
transactionNumber,
|
transactionNumber,
|
||||||
currencyCode: cashflowAccount.currencyCode,
|
currencyCode: cashflowAccount.currencyCode,
|
||||||
exchangeRate: fromDTO?.exchangeRate || 1,
|
exchangeRate: fromDTO?.exchangeRate || 1,
|
||||||
@@ -117,7 +116,7 @@ export class CreateBankTransactionService {
|
|||||||
* @returns {Promise<ICashflowTransaction>}
|
* @returns {Promise<ICashflowTransaction>}
|
||||||
*/
|
*/
|
||||||
public newCashflowTransaction = async (
|
public newCashflowTransaction = async (
|
||||||
newTransactionDTO: ICashflowNewCommandDTO,
|
newTransactionDTO: CreateBankTransactionDto,
|
||||||
userId?: number,
|
userId?: number,
|
||||||
): Promise<BankTransaction> => {
|
): Promise<BankTransaction> => {
|
||||||
// Retrieves the cashflow account or throw not found error.
|
// Retrieves the cashflow account or throw not found error.
|
||||||
|
|||||||
@@ -1,47 +1,64 @@
|
|||||||
|
import { ToNumber } from '@/common/decorators/Validators';
|
||||||
import {
|
import {
|
||||||
IsBoolean,
|
IsBoolean,
|
||||||
IsDate,
|
IsDateString,
|
||||||
|
IsInt,
|
||||||
|
IsNotEmpty,
|
||||||
IsNumber,
|
IsNumber,
|
||||||
IsOptional,
|
IsOptional,
|
||||||
IsString,
|
IsString,
|
||||||
} from 'class-validator';
|
} from 'class-validator';
|
||||||
|
|
||||||
export class CreateBankTransactionDto {
|
export class CreateBankTransactionDto {
|
||||||
@IsDate()
|
@IsDateString()
|
||||||
|
@IsNotEmpty()
|
||||||
date: Date;
|
date: Date;
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
transactionNumber: string;
|
@IsOptional()
|
||||||
|
transactionNumber?: string;
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
referenceNo: string;
|
@IsOptional()
|
||||||
|
referenceNo?: string;
|
||||||
|
|
||||||
|
@IsNotEmpty()
|
||||||
@IsString()
|
@IsString()
|
||||||
transactionType: string;
|
transactionType: string;
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
description: string;
|
description: string;
|
||||||
|
|
||||||
|
@IsNotEmpty()
|
||||||
|
@ToNumber()
|
||||||
@IsNumber()
|
@IsNumber()
|
||||||
amount: number;
|
amount: number;
|
||||||
|
|
||||||
|
@ToNumber()
|
||||||
@IsNumber()
|
@IsNumber()
|
||||||
exchangeRate: number;
|
exchangeRate: number = 1;
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
currencyCode: string;
|
currencyCode: string;
|
||||||
|
|
||||||
@IsNumber()
|
@IsNotEmpty()
|
||||||
|
@ToNumber()
|
||||||
|
@IsInt()
|
||||||
creditAccountId: number;
|
creditAccountId: number;
|
||||||
|
|
||||||
@IsNumber()
|
@IsNotEmpty()
|
||||||
|
@ToNumber()
|
||||||
|
@IsInt()
|
||||||
cashflowAccountId: number;
|
cashflowAccountId: number;
|
||||||
|
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
publish: boolean;
|
@IsOptional()
|
||||||
|
publish: boolean = true;
|
||||||
|
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsNumber()
|
@ToNumber()
|
||||||
|
@IsInt()
|
||||||
branchId?: number;
|
branchId?: number;
|
||||||
|
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@@ -53,6 +70,6 @@ export class CreateBankTransactionDto {
|
|||||||
plaidAccountId?: string;
|
plaidAccountId?: string;
|
||||||
|
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsNumber()
|
@IsInt()
|
||||||
uncategorizedTransactionId?: number;
|
uncategorizedTransactionId?: number;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common';
|
|||||||
import { getBankAccountTransactionsDefaultQuery } from './_utils';
|
import { getBankAccountTransactionsDefaultQuery } from './_utils';
|
||||||
import { GetBankAccountTransactionsRepository } from './GetBankAccountTransactionsRepo.service';
|
import { GetBankAccountTransactionsRepository } from './GetBankAccountTransactionsRepo.service';
|
||||||
import { GetBankAccountTransactions } from './GetBankAccountTransactions';
|
import { GetBankAccountTransactions } from './GetBankAccountTransactions';
|
||||||
import { ICashflowAccountTransactionsQuery } from '../../types/BankingTransactions.types';
|
import { GetBankTransactionsQueryDto } from '../../dtos/GetBankTranasctionsQuery.dto';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class GetBankAccountTransactionsService {
|
export class GetBankAccountTransactionsService {
|
||||||
@@ -16,7 +16,7 @@ export class GetBankAccountTransactionsService {
|
|||||||
* @return {Promise<IInvetoryItemDetailDOO>}
|
* @return {Promise<IInvetoryItemDetailDOO>}
|
||||||
*/
|
*/
|
||||||
public async bankAccountTransactions(
|
public async bankAccountTransactions(
|
||||||
query: ICashflowAccountTransactionsQuery,
|
query: GetBankTransactionsQueryDto,
|
||||||
) {
|
) {
|
||||||
const parsedQuery = {
|
const parsedQuery = {
|
||||||
...getBankAccountTransactionsDefaultQuery(),
|
...getBankAccountTransactionsDefaultQuery(),
|
||||||
|
|||||||
@@ -1,35 +1,23 @@
|
|||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { initialize } from 'objection';
|
|
||||||
import { Knex } from 'knex';
|
|
||||||
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
|
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
|
||||||
import { UncategorizedBankTransaction } from '../models/UncategorizedBankTransaction';
|
import { UncategorizedBankTransaction } from '../models/UncategorizedBankTransaction';
|
||||||
import { UncategorizedTransactionTransformer } from '../../BankingCategorize/commands/UncategorizedTransaction.transformer';
|
import { UncategorizedTransactionTransformer } from '../../BankingCategorize/commands/UncategorizedTransaction.transformer';
|
||||||
import { GetUncategorizedTransactionsQueryDto } from '../dtos/GetUncategorizedTransactionsQuery.dto';
|
import { GetUncategorizedTransactionsQueryDto } from '../dtos/GetUncategorizedTransactionsQuery.dto';
|
||||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
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()
|
@Injectable()
|
||||||
export class GetUncategorizedTransactions {
|
export class GetUncategorizedTransactions {
|
||||||
|
/**
|
||||||
|
* @param {TransformerInjectable} transformer
|
||||||
|
* @param {UncategorizedBankTransaction.name} uncategorizedBankTransactionModel
|
||||||
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
private readonly transformer: TransformerInjectable,
|
private readonly transformer: TransformerInjectable,
|
||||||
|
|
||||||
@Inject(TENANCY_DB_CONNECTION)
|
|
||||||
private readonly tenantDb: () => Knex,
|
|
||||||
|
|
||||||
@Inject(UncategorizedBankTransaction.name)
|
@Inject(UncategorizedBankTransaction.name)
|
||||||
private readonly uncategorizedBankTransactionModel: TenantModelProxy<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>,
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,7 +27,7 @@ export class GetUncategorizedTransactions {
|
|||||||
*/
|
*/
|
||||||
public async getTransactions(
|
public async getTransactions(
|
||||||
accountId: number,
|
accountId: number,
|
||||||
query: GetUncategorizedTransactionsQueryDto
|
query: GetUncategorizedTransactionsQueryDto,
|
||||||
) {
|
) {
|
||||||
// Parsed query with default values.
|
// Parsed query with default values.
|
||||||
const _query = {
|
const _query = {
|
||||||
@@ -47,16 +35,9 @@ export class GetUncategorizedTransactions {
|
|||||||
pageSize: 20,
|
pageSize: 20,
|
||||||
...query,
|
...query,
|
||||||
};
|
};
|
||||||
|
|
||||||
await initialize(this.tenantDb(), [
|
|
||||||
this.accountModel(),
|
|
||||||
this.uncategorizedBankTransactionModel(),
|
|
||||||
this.recognizedTransactionModel(),
|
|
||||||
this.matchedTransactionModel(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
const { results, pagination } =
|
const { results, pagination } =
|
||||||
await this.uncategorizedBankTransactionModel().query()
|
await this.uncategorizedBankTransactionModel()
|
||||||
|
.query()
|
||||||
.onBuild((q) => {
|
.onBuild((q) => {
|
||||||
q.where('accountId', accountId);
|
q.where('accountId', accountId);
|
||||||
q.where('categorized', false);
|
q.where('categorized', false);
|
||||||
@@ -89,7 +70,7 @@ export class GetUncategorizedTransactions {
|
|||||||
|
|
||||||
const data = await this.transformer.transform(
|
const data = await this.transformer.transform(
|
||||||
results,
|
results,
|
||||||
new UncategorizedTransactionTransformer()
|
new UncategorizedTransactionTransformer(),
|
||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
data,
|
data,
|
||||||
|
|||||||
@@ -3,7 +3,10 @@ import { OnEvent } from '@nestjs/event-emitter';
|
|||||||
import { BankTransactionAutoIncrement } from '../commands/BankTransactionAutoIncrement.service';
|
import { BankTransactionAutoIncrement } from '../commands/BankTransactionAutoIncrement.service';
|
||||||
import { BankTransactionGLEntriesService } from '../commands/BankTransactionGLEntries';
|
import { BankTransactionGLEntriesService } from '../commands/BankTransactionGLEntries';
|
||||||
import { events } from '@/common/events/events';
|
import { events } from '@/common/events/events';
|
||||||
import { ICommandCashflowCreatedPayload, ICommandCashflowDeletedPayload } from '../types/BankingTransactions.types';
|
import {
|
||||||
|
ICommandCashflowCreatedPayload,
|
||||||
|
ICommandCashflowDeletedPayload,
|
||||||
|
} from '../types/BankingTransactions.types';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class BankingTransactionGLEntriesSubscriber {
|
export class BankingTransactionGLEntriesSubscriber {
|
||||||
@@ -56,5 +59,5 @@ export class BankingTransactionGLEntriesSubscriber {
|
|||||||
cashflowTransactionId,
|
cashflowTransactionId,
|
||||||
trx,
|
trx,
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -492,7 +492,7 @@ export class Bill extends TenantBaseModel {
|
|||||||
TaxRateTransaction,
|
TaxRateTransaction,
|
||||||
} = require('../../TaxRates/models/TaxRateTransaction.model');
|
} = require('../../TaxRates/models/TaxRateTransaction.model');
|
||||||
const { Document } = require('../../ChromiumlyTenancy/models/Document');
|
const { Document } = require('../../ChromiumlyTenancy/models/Document');
|
||||||
// const { MatchedBankTransaction } = require('models/MatchedBankTransaction');
|
const { MatchedBankTransaction } = require('../../BankingMatching/models/MatchedBankTransaction');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
vendor: {
|
vendor: {
|
||||||
@@ -590,17 +590,17 @@ export class Bill extends TenantBaseModel {
|
|||||||
/**
|
/**
|
||||||
* Bill may belongs to matched bank transaction.
|
* Bill may belongs to matched bank transaction.
|
||||||
*/
|
*/
|
||||||
// matchedBankTransaction: {
|
matchedBankTransaction: {
|
||||||
// relation: Model.HasManyRelation,
|
relation: Model.HasManyRelation,
|
||||||
// modelClass: MatchedBankTransaction,
|
modelClass: MatchedBankTransaction,
|
||||||
// join: {
|
join: {
|
||||||
// from: 'bills.id',
|
from: 'bills.id',
|
||||||
// to: 'matched_bank_transactions.referenceId',
|
to: 'matched_bank_transactions.referenceId',
|
||||||
// },
|
},
|
||||||
// filter(query) {
|
filter(query) {
|
||||||
// query.where('reference_type', 'Bill');
|
query.where('reference_type', 'Bill');
|
||||||
// },
|
},
|
||||||
// },
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import * as R from 'ramda';
|
import * as R from 'ramda';
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import validator from 'is-my-json-valid';
|
import * as validator from 'is-my-json-valid';
|
||||||
import { IFilterRole } from './DynamicFilter/DynamicFilter.types';
|
import { IFilterRole } from './DynamicFilter/DynamicFilter.types';
|
||||||
import { DynamicFilterAdvancedFilter } from './DynamicFilter/DynamicFilterAdvancedFilter';
|
import { DynamicFilterAdvancedFilter } from './DynamicFilter/DynamicFilterAdvancedFilter';
|
||||||
import { DynamicFilterRoleAbstractor } from './DynamicFilter/DynamicFilterRoleAbstractor';
|
import { DynamicFilterRoleAbstractor } from './DynamicFilter/DynamicFilterRoleAbstractor';
|
||||||
@@ -21,7 +21,7 @@ export class DynamicListFilterRoles extends DynamicFilterRoleAbstractor {
|
|||||||
properties: {
|
properties: {
|
||||||
condition: { type: 'string' },
|
condition: { type: 'string' },
|
||||||
fieldKey: { type: 'string' },
|
fieldKey: { type: 'string' },
|
||||||
value: { type: 'string' },
|
// value: { type: ['number', 'string'] },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const invalidFields = filterRoles.filter((filterRole) => {
|
const invalidFields = filterRoles.filter((filterRole) => {
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ export class Expense extends TenantBaseModel {
|
|||||||
const { ExpenseCategory } = require('./ExpenseCategory.model');
|
const { ExpenseCategory } = require('./ExpenseCategory.model');
|
||||||
const { Document } = require('../../ChromiumlyTenancy/models/Document');
|
const { Document } = require('../../ChromiumlyTenancy/models/Document');
|
||||||
const { Branch } = require('../../Branches/models/Branch.model');
|
const { Branch } = require('../../Branches/models/Branch.model');
|
||||||
// const { MatchedBankTransaction } = require('models/MatchedBankTransaction');
|
const { MatchedBankTransaction } = require('../../BankingMatching/models/MatchedBankTransaction');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
/**
|
/**
|
||||||
@@ -263,20 +263,20 @@ export class Expense extends TenantBaseModel {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Expense may belongs to matched bank transaction.
|
* Expense may belongs to matched bank transaction.
|
||||||
// */
|
*/
|
||||||
// matchedBankTransaction: {
|
matchedBankTransaction: {
|
||||||
// relation: Model.HasManyRelation,
|
relation: Model.HasManyRelation,
|
||||||
// modelClass: MatchedBankTransaction,
|
modelClass: MatchedBankTransaction,
|
||||||
// join: {
|
join: {
|
||||||
// from: 'expenses_transactions.id',
|
from: 'expenses_transactions.id',
|
||||||
// to: 'matched_bank_transactions.referenceId',
|
to: 'matched_bank_transactions.referenceId',
|
||||||
// },
|
},
|
||||||
// filter(query) {
|
filter(query) {
|
||||||
// query.where('reference_type', 'Expense');
|
query.where('reference_type', 'Expense');
|
||||||
// },
|
},
|
||||||
// },
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ export class ManualJournal extends TenantBaseModel {
|
|||||||
const { AccountTransaction } = require('../../Accounts/models/AccountTransaction.model');
|
const { AccountTransaction } = require('../../Accounts/models/AccountTransaction.model');
|
||||||
const { ManualJournalEntry } = require('./ManualJournalEntry');
|
const { ManualJournalEntry } = require('./ManualJournalEntry');
|
||||||
const { Document } = require('../../ChromiumlyTenancy/models/Document');
|
const { Document } = require('../../ChromiumlyTenancy/models/Document');
|
||||||
// const { MatchedBankTransaction } = require('models/MatchedBankTransaction');
|
const { MatchedBankTransaction } = require('../../BankingMatching/models/MatchedBankTransaction');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
entries: {
|
entries: {
|
||||||
@@ -171,17 +171,17 @@ export class ManualJournal extends TenantBaseModel {
|
|||||||
/**
|
/**
|
||||||
* Manual journal may belongs to matched bank transaction.
|
* Manual journal may belongs to matched bank transaction.
|
||||||
*/
|
*/
|
||||||
// matchedBankTransaction: {
|
matchedBankTransaction: {
|
||||||
// relation: Model.BelongsToOneRelation,
|
relation: Model.BelongsToOneRelation,
|
||||||
// modelClass: MatchedBankTransaction,
|
modelClass: MatchedBankTransaction,
|
||||||
// join: {
|
join: {
|
||||||
// from: 'manual_journals.id',
|
from: 'manual_journals.id',
|
||||||
// to: 'matched_bank_transactions.referenceId',
|
to: 'matched_bank_transactions.referenceId',
|
||||||
// },
|
},
|
||||||
// filter(query) {
|
filter(query) {
|
||||||
// query.where('reference_type', 'ManualJournal');
|
query.where('reference_type', 'ManualJournal');
|
||||||
// },
|
},
|
||||||
// },
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -512,7 +512,7 @@ export class SaleInvoice extends TenantBaseModel{
|
|||||||
TaxRateTransaction,
|
TaxRateTransaction,
|
||||||
} = require('../../TaxRates/models/TaxRateTransaction.model');
|
} = require('../../TaxRates/models/TaxRateTransaction.model');
|
||||||
const { Document } = require('../../ChromiumlyTenancy/models/Document');
|
const { Document } = require('../../ChromiumlyTenancy/models/Document');
|
||||||
// const { MatchedBankTransaction } = require('models/MatchedBankTransaction');
|
const { MatchedBankTransaction } = require('../../BankingMatching/models/MatchedBankTransaction');
|
||||||
const {
|
const {
|
||||||
TransactionPaymentServiceEntry,
|
TransactionPaymentServiceEntry,
|
||||||
} = require('../../PaymentServices/models/TransactionPaymentServiceEntry.model');
|
} = require('../../PaymentServices/models/TransactionPaymentServiceEntry.model');
|
||||||
@@ -667,17 +667,17 @@ export class SaleInvoice extends TenantBaseModel{
|
|||||||
/**
|
/**
|
||||||
* Sale invocie may belongs to matched bank transaction.
|
* Sale invocie may belongs to matched bank transaction.
|
||||||
*/
|
*/
|
||||||
// matchedBankTransaction: {
|
matchedBankTransaction: {
|
||||||
// relation: Model.HasManyRelation,
|
relation: Model.HasManyRelation,
|
||||||
// modelClass: MatchedBankTransaction,
|
modelClass: MatchedBankTransaction,
|
||||||
// join: {
|
join: {
|
||||||
// from: 'sales_invoices.id',
|
from: 'sales_invoices.id',
|
||||||
// to: 'matched_bank_transactions.referenceId',
|
to: 'matched_bank_transactions.referenceId',
|
||||||
// },
|
},
|
||||||
// filter(query) {
|
filter(query) {
|
||||||
// query.where('reference_type', 'SaleInvoice');
|
query.where('reference_type', 'SaleInvoice');
|
||||||
// },
|
},
|
||||||
// },
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sale invoice may belongs to payment methods entries.
|
* Sale invoice may belongs to payment methods entries.
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { EnsureTenantIsSeededGuard } from "./EnsureTenantIsSeeded.guards";
|
|||||||
import { APP_GUARD } from "@nestjs/core";
|
import { APP_GUARD } from "@nestjs/core";
|
||||||
import { TenancyContext } from "./TenancyContext.service";
|
import { TenancyContext } from "./TenancyContext.service";
|
||||||
import { TenantController } from "./Tenant.controller";
|
import { TenantController } from "./Tenant.controller";
|
||||||
|
import { TenancyInitializeModelsGuard } from "./TenancyInitializeModels.guard";
|
||||||
|
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
@@ -23,6 +24,10 @@ import { TenantController } from "./Tenant.controller";
|
|||||||
{
|
{
|
||||||
provide: APP_GUARD,
|
provide: APP_GUARD,
|
||||||
useClass: EnsureTenantIsSeededGuard
|
useClass: EnsureTenantIsSeededGuard
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: APP_GUARD,
|
||||||
|
useClass: TenancyInitializeModelsGuard
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
import {
|
||||||
|
CanActivate,
|
||||||
|
ExecutionContext,
|
||||||
|
Inject,
|
||||||
|
Injectable,
|
||||||
|
SetMetadata,
|
||||||
|
} from '@nestjs/common';
|
||||||
|
import { Reflector } from '@nestjs/core';
|
||||||
|
import { IS_PUBLIC_ROUTE } from '../Auth/Auth.constants';
|
||||||
|
import { TENANT_MODELS_INIT } from './TenantModelsInitialize.module';
|
||||||
|
|
||||||
|
export const IGNORE_TENANT_MODELS_INITIALIZE =
|
||||||
|
'IGNORE_TENANT_MODELS_INITIALIZE';
|
||||||
|
export const IgnoreTenantModelsInitialize = () =>
|
||||||
|
SetMetadata(IGNORE_TENANT_MODELS_INITIALIZE, true);
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class TenancyInitializeModelsGuard implements CanActivate {
|
||||||
|
constructor(
|
||||||
|
@Inject(TENANT_MODELS_INIT)
|
||||||
|
private readonly tenantModelsInit: () => Promise<boolean>,
|
||||||
|
private reflector: Reflector,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize tenant models if the route is decorated with TriggerTenantModelsInitialize.
|
||||||
|
* @param {ExecutionContext} context
|
||||||
|
* @returns {Promise<boolean>}
|
||||||
|
*/
|
||||||
|
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||||
|
const isPublic = this.reflector.getAllAndOverride<boolean>(
|
||||||
|
IS_PUBLIC_ROUTE,
|
||||||
|
[context.getHandler(), context.getClass()],
|
||||||
|
);
|
||||||
|
// Skip initialization for public routes
|
||||||
|
if (isPublic) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const shouldIgnoreInitialization =
|
||||||
|
this.reflector.getAllAndOverride<boolean>(
|
||||||
|
IGNORE_TENANT_MODELS_INITIALIZE,
|
||||||
|
[context.getHandler(), context.getClass()],
|
||||||
|
);
|
||||||
|
// Initialize models unless the route is decorated with IgnoreTenantModelsInitialize
|
||||||
|
if (!shouldIgnoreInitialization) {
|
||||||
|
try {
|
||||||
|
await this.tenantModelsInit();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to initialize tenant models:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
import { ContextIdFactory, ModuleRef } from '@nestjs/core';
|
||||||
|
import { ClsModule } from 'nestjs-cls';
|
||||||
|
import { Global, Module } from '@nestjs/common';
|
||||||
|
import { Knex } from 'knex';
|
||||||
|
import { initialize } from 'objection';
|
||||||
|
import { TENANCY_DB_CONNECTION } from './TenancyDB/TenancyDB.constants';
|
||||||
|
|
||||||
|
const RegisteredModels = [
|
||||||
|
'SaleInvoice',
|
||||||
|
'Bill',
|
||||||
|
'Expense',
|
||||||
|
'BankTransaction',
|
||||||
|
'MatchedBankTransaction',
|
||||||
|
'ManualJournalEntry',
|
||||||
|
'Account',
|
||||||
|
'UncategorizedBankTransaction',
|
||||||
|
'RecognizedBankTransaction',
|
||||||
|
];
|
||||||
|
export const TENANT_MODELS_INIT = 'TENANT_MODELS_INIT';
|
||||||
|
|
||||||
|
const provider = ClsModule.forFeatureAsync({
|
||||||
|
provide: TENANT_MODELS_INIT,
|
||||||
|
inject: [TENANCY_DB_CONNECTION, ModuleRef],
|
||||||
|
useFactory: (tenantKnex: () => Knex, moduleRef: ModuleRef) => async () => {
|
||||||
|
const knexInstance = tenantKnex();
|
||||||
|
const contextId = ContextIdFactory.create();
|
||||||
|
const models = await Promise.all(
|
||||||
|
RegisteredModels.map((model) => {
|
||||||
|
return moduleRef.resolve(model, contextId, { strict: false });
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
const modelsInstances = models.map((model) => model());
|
||||||
|
|
||||||
|
if (modelsInstances.length > 0) {
|
||||||
|
try {
|
||||||
|
// Initialize all models with the knex instance
|
||||||
|
await initialize(knexInstance, modelsInstances);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error initializing models:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
strict: true,
|
||||||
|
type: 'function',
|
||||||
|
});
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [provider],
|
||||||
|
exports: [provider],
|
||||||
|
})
|
||||||
|
@Global()
|
||||||
|
export class TenantModelsInitializeModule {}
|
||||||
@@ -248,7 +248,7 @@ export function useCategorizeTransaction(props) {
|
|||||||
const apiRequest = useApiRequest();
|
const apiRequest = useApiRequest();
|
||||||
|
|
||||||
return useMutation(
|
return useMutation(
|
||||||
(values) => apiRequest.post(`banking/transactions/categorize`, values),
|
(values) => apiRequest.post(`banking/categorize`, values),
|
||||||
{
|
{
|
||||||
onSuccess: (res, id) => {
|
onSuccess: (res, id) => {
|
||||||
// Invalidate queries.
|
// Invalidate queries.
|
||||||
@@ -274,7 +274,7 @@ export function useUncategorizeTransaction(props) {
|
|||||||
const apiRequest = useApiRequest();
|
const apiRequest = useApiRequest();
|
||||||
|
|
||||||
return useMutation(
|
return useMutation(
|
||||||
(id: number) => apiRequest.post(`banking/transactions/${id}/uncategorize`),
|
(id: number) => apiRequest.delete(`banking/categorize/${id}`),
|
||||||
{
|
{
|
||||||
onSuccess: (res, id) => {
|
onSuccess: (res, id) => {
|
||||||
// Invalidate queries.
|
// Invalidate queries.
|
||||||
|
|||||||
Reference in New Issue
Block a user