refactor: tenant proxy providers

This commit is contained in:
Ahmed Bouhuolia
2025-02-15 23:52:12 +02:00
parent 36851d3209
commit 5c0bb52b59
302 changed files with 2396 additions and 1677 deletions

View File

@@ -22,7 +22,7 @@ import { DynamicListModule } from '../DynamicListing/DynamicList.module';
const models = [RegisterTenancyModel(BankAccount)];
@Module({
imports: [TenancyDatabaseModule, DynamicListModule],
imports: [TenancyDatabaseModule, DynamicListModule, ...models],
controllers: [AccountsController],
providers: [
AccountsApplication,
@@ -38,7 +38,6 @@ const models = [RegisterTenancyModel(BankAccount)];
GetAccountTypesService,
GetAccountTransactionsService,
GetAccountsService,
...models,
],
exports: [AccountRepository, CreateAccountService, ...models],
})

View File

@@ -6,16 +6,17 @@ import { AccountRepository } from './repositories/Account.repository';
import { UnitOfWork } from '../Tenancy/TenancyDB/UnitOfWork.service';
import { EventEmitter2 } from '@nestjs/event-emitter';
import { events } from '@/common/events/events';
import { TenantModelProxy } from '../System/models/TenantBaseModel';
@Injectable()
export class ActivateAccount {
constructor(
private readonly eventEmitter: EventEmitter2,
private readonly uow: UnitOfWork,
private readonly accountRepository: AccountRepository,
@Inject(Account.name)
private readonly accountModel: typeof Account,
private readonly accountRepository: AccountRepository,
private readonly accountModel: TenantModelProxy<typeof Account>,
) {}
/**
@@ -25,7 +26,7 @@ export class ActivateAccount {
*/
public activateAccount = async (accountId: number, activate?: boolean) => {
// Retrieve the given account or throw not found error.
const oldAccount = await this.accountModel
const oldAccount = await this.accountModel()
.query()
.findById(accountId)
.throwIfNotFound();

View File

@@ -9,12 +9,13 @@ import { AccountRepository } from './repositories/Account.repository';
import { AccountTypesUtils } from './utils/AccountType.utils';
import { CreateAccountDTO } from './CreateAccount.dto';
import { EditAccountDTO } from './EditAccount.dto';
import { TenantModelProxy } from '../System/models/TenantBaseModel';
@Injectable({ scope: Scope.REQUEST })
export class CommandAccountValidators {
constructor(
@Inject(Account.name)
private readonly accountModel: typeof Account,
private readonly accountModel: TenantModelProxy<typeof Account>,
private readonly accountRepository: AccountRepository,
) {}
@@ -66,7 +67,7 @@ export class CommandAccountValidators {
accountId: number,
notAccountId?: number,
) {
const parentAccount = await this.accountModel
const parentAccount = await this.accountModel()
.query()
.findById(accountId)
.onBuild((query) => {
@@ -89,7 +90,7 @@ export class CommandAccountValidators {
accountCode: string,
notAccountId?: number,
) {
const account = await this.accountModel
const account = await this.accountModel()
.query()
.where('code', accountCode)
.onBuild((query) => {

View File

@@ -14,12 +14,13 @@ import { TenancyContext } from '../Tenancy/TenancyContext.service';
import { events } from '@/common/events/events';
import { CreateAccountDTO } from './CreateAccount.dto';
import { PartialModelObject } from 'objection';
import { TenantModelProxy } from '../System/models/TenantBaseModel';
@Injectable()
export class CreateAccountService {
constructor(
@Inject(Account.name)
private readonly accountModel: typeof Account,
private readonly accountModel: TenantModelProxy<typeof Account>,
private readonly eventEmitter: EventEmitter2,
private readonly uow: UnitOfWork,
private readonly validator: CommandAccountValidators,
@@ -121,9 +122,11 @@ export class CreateAccountService {
} as IAccountEventCreatingPayload);
// Inserts account to the storage.
const account = await this.accountModel.query().insert({
...accountInputModel,
});
const account = await this.accountModel()
.query()
.insert({
...accountInputModel,
});
// Triggers `onAccountCreated` event.
await this.eventEmitter.emitAsync(events.accounts.onCreated, {
account,

View File

@@ -7,11 +7,14 @@ import { EventEmitter2 } from '@nestjs/event-emitter';
import { UnitOfWork } from '../Tenancy/TenancyDB/UnitOfWork.service';
import { events } from '@/common/events/events';
import { IAccountEventDeletedPayload } from './Accounts.types';
import { TenantModelProxy } from '../System/models/TenantBaseModel';
@Injectable()
export class DeleteAccount {
constructor(
@Inject(Account.name) private accountModel: typeof Account,
@Inject(Account.name)
private accountModel: TenantModelProxy<typeof Account>,
private eventEmitter: EventEmitter2,
private uow: UnitOfWork,
private validator: CommandAccountValidators,
@@ -38,7 +41,7 @@ export class DeleteAccount {
? parentAccountId
: [parentAccountId];
await this.accountModel
await this.accountModel()
.query(trx)
.whereIn('parent_account_id', accountsIds)
.patch({ parentAccountId: null });
@@ -50,7 +53,7 @@ export class DeleteAccount {
*/
public deleteAccount = async (accountId: number): Promise<void> => {
// Retrieve account or not found service error.
const oldAccount = await this.accountModel.query().findById(accountId);
const oldAccount = await this.accountModel().query().findById(accountId);
// Authorize before delete account.
await this.authorize(accountId, oldAccount);
@@ -67,7 +70,7 @@ export class DeleteAccount {
await this.unassociateChildrenAccountsFromParent(accountId, trx);
// Deletes account by the given id.
await this.accountModel.query(trx).deleteById(accountId);
await this.accountModel().query(trx).deleteById(accountId);
// Triggers `onAccountDeleted` event.
await this.eventEmitter.emitAsync(events.accounts.onDeleted, {

View File

@@ -6,6 +6,7 @@ import { EventEmitter2 } from '@nestjs/event-emitter';
import { UnitOfWork } from '../Tenancy/TenancyDB/UnitOfWork.service';
import { events } from '@/common/events/events';
import { EditAccountDTO } from './EditAccount.dto';
import { TenantModelProxy } from '../System/models/TenantBaseModel';
@Injectable()
export class EditAccount {
@@ -15,7 +16,7 @@ export class EditAccount {
private readonly validator: CommandAccountValidators,
@Inject(Account.name)
private readonly accountModel: typeof Account,
private readonly accountModel: TenantModelProxy<typeof Account>,
) {}
/**
@@ -66,7 +67,7 @@ export class EditAccount {
accountDTO: EditAccountDTO,
): Promise<Account> {
// Retrieve the old account or throw not found service error.
const oldAccount = await this.accountModel
const oldAccount = await this.accountModel()
.query()
.findById(accountId)
.throwIfNotFound();
@@ -82,7 +83,7 @@ export class EditAccount {
accountDTO,
});
// Update the account on the storage.
const account = await this.accountModel
const account = await this.accountModel()
.query(trx)
.findById(accountId)
.updateAndFetch({ ...accountDTO });

View File

@@ -5,12 +5,13 @@ import { AccountRepository } from './repositories/Account.repository';
import { TransformerInjectable } from '../Transformer/TransformerInjectable.service';
import { EventEmitter2 } from '@nestjs/event-emitter';
import { events } from '@/common/events/events';
import { TenantModelProxy } from '../System/models/TenantBaseModel';
@Injectable()
export class GetAccount {
constructor(
@Inject(Account.name)
private readonly accountModel: typeof Account,
private readonly accountModel: TenantModelProxy<typeof Account>,
private readonly accountRepository: AccountRepository,
private readonly transformer: TransformerInjectable,
private readonly eventEmitter: EventEmitter2,
@@ -22,7 +23,7 @@ export class GetAccount {
*/
public getAccount = async (accountId: number) => {
// Find the given account or throw not found error.
const account = await this.accountModel
const account = await this.accountModel()
.query()
.findById(accountId)
.withGraphFetched('plaidItem')

View File

@@ -7,6 +7,7 @@ import { AccountTransaction } from './models/AccountTransaction.model';
import { Account } from './models/Account.model';
import { Inject, Injectable } from '@nestjs/common';
import { TransformerInjectable } from '../Transformer/TransformerInjectable.service';
import { TenantModelProxy } from '../System/models/TenantBaseModel';
@Injectable()
export class GetAccountTransactionsService {
@@ -14,10 +15,12 @@ export class GetAccountTransactionsService {
private readonly transformer: TransformerInjectable,
@Inject(AccountTransaction.name)
private readonly accountTransaction: typeof AccountTransaction,
private readonly accountTransaction: TenantModelProxy<
typeof AccountTransaction
>,
@Inject(Account.name)
private readonly account: typeof Account,
private readonly account: TenantModelProxy<typeof Account>,
) {}
/**
@@ -29,9 +32,9 @@ export class GetAccountTransactionsService {
): Promise<IGetAccountTransactionPOJO[]> => {
// Retrieve the given account or throw not found error.
if (filter.accountId) {
await this.account.query().findById(filter.accountId).throwIfNotFound();
await this.account().query().findById(filter.accountId).throwIfNotFound();
}
const transactions = await this.accountTransaction
const transactions = await this.accountTransaction()
.query()
.onBuild((query) => {
query.orderBy('date', 'DESC');

View File

@@ -7,6 +7,7 @@ import { TransformerInjectable } from '../Transformer/TransformerInjectable.serv
import { Account } from './models/Account.model';
import { AccountRepository } from './repositories/Account.repository';
import { IFilterMeta } from '@/interfaces/Model';
import { TenantModelProxy } from '../System/models/TenantBaseModel';
@Injectable()
export class GetAccountsService {
@@ -16,7 +17,7 @@ export class GetAccountsService {
private readonly accountRepository: AccountRepository,
@Inject(Account.name)
private readonly accountModel: typeof Account,
private readonly accountModel: TenantModelProxy<typeof Account>,
) {}
/**
@@ -32,14 +33,16 @@ export class GetAccountsService {
// Dynamic list service.
const dynamicList = await this.dynamicListService.dynamicList(
this.accountModel,
this.accountModel(),
filter,
);
// Retrieve accounts model based on the given query.
const accounts = await this.accountModel.query().onBuild((builder) => {
dynamicList.buildQuery()(builder);
builder.modify('inactiveMode', filter.inactiveMode);
});
const accounts = await this.accountModel()
.query()
.onBuild((builder) => {
dynamicList.buildQuery()(builder);
builder.modify('inactiveMode', filter.inactiveMode);
});
const accountsGraph = await this.accountRepository.getDependencyGraph();
// Retrieves the transformed accounts collection.