fix: only inactive accounts filter

This commit is contained in:
Ahmed Bouhuolia
2025-11-02 19:58:26 +02:00
parent 77dc0778a3
commit fdec94a3f7
5 changed files with 54 additions and 13 deletions

View File

@@ -11,11 +11,11 @@ import {
import { AccountsApplication } from './AccountsApplication.service'; import { AccountsApplication } from './AccountsApplication.service';
import { CreateAccountDTO } from './CreateAccount.dto'; import { CreateAccountDTO } from './CreateAccount.dto';
import { EditAccountDTO } from './EditAccount.dto'; import { EditAccountDTO } from './EditAccount.dto';
import { IAccountsFilter } from './Accounts.types';
import { import {
ApiExtraModels, ApiExtraModels,
ApiOperation, ApiOperation,
ApiParam, ApiParam,
ApiQuery,
ApiResponse, ApiResponse,
ApiTags, ApiTags,
getSchemaPath, getSchemaPath,
@@ -24,6 +24,7 @@ import { AccountResponseDto } from './dtos/AccountResponse.dto';
import { AccountTypeResponseDto } from './dtos/AccountTypeResponse.dto'; import { AccountTypeResponseDto } from './dtos/AccountTypeResponse.dto';
import { GetAccountTransactionResponseDto } from './dtos/GetAccountTransactionResponse.dto'; import { GetAccountTransactionResponseDto } from './dtos/GetAccountTransactionResponse.dto';
import { GetAccountTransactionsQueryDto } from './dtos/GetAccountTransactionsQuery.dto'; import { GetAccountTransactionsQueryDto } from './dtos/GetAccountTransactionsQuery.dto';
import { GetAccountsQueryDto } from './dtos/GetAccountsQuery.dto';
import { ApiCommonHeaders } from '@/common/decorators/ApiCommonHeaders'; import { ApiCommonHeaders } from '@/common/decorators/ApiCommonHeaders';
@Controller('accounts') @Controller('accounts')
@@ -33,7 +34,7 @@ import { ApiCommonHeaders } from '@/common/decorators/ApiCommonHeaders';
@ApiExtraModels(GetAccountTransactionResponseDto) @ApiExtraModels(GetAccountTransactionResponseDto)
@ApiCommonHeaders() @ApiCommonHeaders()
export class AccountsController { export class AccountsController {
constructor(private readonly accountsApplication: AccountsApplication) {} constructor(private readonly accountsApplication: AccountsApplication) { }
@Post() @Post()
@ApiOperation({ summary: 'Create an account' }) @ApiOperation({ summary: 'Create an account' })
@@ -178,7 +179,19 @@ export class AccountsController {
items: { $ref: getSchemaPath(AccountResponseDto) }, items: { $ref: getSchemaPath(AccountResponseDto) },
}, },
}) })
async getAccounts(@Query() filter: Partial<IAccountsFilter>) { @ApiQuery({
name: 'onlyInactive',
required: false,
type: Boolean,
description: 'Filter to show only inactive accounts',
})
@ApiQuery({
name: 'structure',
required: false,
type: String,
description: 'Structure type for the accounts list',
})
async getAccounts(@Query() filter: GetAccountsQueryDto) {
return this.accountsApplication.getAccounts(filter); return this.accountsApplication.getAccounts(filter);
} }
} }

View File

@@ -10,10 +10,11 @@ import { GetAccount } from './GetAccount.service';
import { ActivateAccount } from './ActivateAccount.service'; import { ActivateAccount } from './ActivateAccount.service';
import { GetAccountTypesService } from './GetAccountTypes.service'; import { GetAccountTypesService } from './GetAccountTypes.service';
import { GetAccountTransactionsService } from './GetAccountTransactions.service'; import { GetAccountTransactionsService } from './GetAccountTransactions.service';
import { IAccountsFilter, IAccountsTransactionsFilter } from './Accounts.types'; import { IAccountsTransactionsFilter } from './Accounts.types';
import { GetAccountsService } from './GetAccounts.service'; import { GetAccountsService } from './GetAccounts.service';
import { IFilterMeta } from '@/interfaces/Model'; import { IFilterMeta } from '@/interfaces/Model';
import { GetAccountTransactionResponseDto } from './dtos/GetAccountTransactionResponse.dto'; import { GetAccountTransactionResponseDto } from './dtos/GetAccountTransactionResponse.dto';
import { GetAccountsQueryDto } from './dtos/GetAccountsQuery.dto';
@Injectable() @Injectable()
export class AccountsApplication { export class AccountsApplication {
@@ -36,7 +37,7 @@ export class AccountsApplication {
private readonly getAccountService: GetAccount, private readonly getAccountService: GetAccount,
private readonly getAccountTransactionsService: GetAccountTransactionsService, private readonly getAccountTransactionsService: GetAccountTransactionsService,
private readonly getAccountsService: GetAccountsService, private readonly getAccountsService: GetAccountsService,
) {} ) { }
/** /**
* Creates a new account. * Creates a new account.
@@ -108,11 +109,11 @@ export class AccountsApplication {
/** /**
* Retrieves the accounts list. * Retrieves the accounts list.
* @param {IAccountsFilter} filterDTO - Filter DTO. * @param {GetAccountsQueryDto} filterDTO - Filter DTO.
* @returns {Promise<{ accounts: IAccountResponse[]; filterMeta: IFilterMeta }>} * @returns {Promise<{ accounts: IAccountResponse[]; filterMeta: IFilterMeta }>}
*/ */
public getAccounts = ( public getAccounts = (
filterDTO: Partial<IAccountsFilter>, filterDTO: GetAccountsQueryDto,
): Promise<{ accounts: Account[]; filterMeta: IFilterMeta }> => { ): Promise<{ accounts: Account[]; filterMeta: IFilterMeta }> => {
return this.getAccountsService.getAccountsList(filterDTO); return this.getAccountsService.getAccountsList(filterDTO);
}; };

View File

@@ -8,6 +8,7 @@ import { Account } from './models/Account.model';
import { AccountRepository } from './repositories/Account.repository'; import { AccountRepository } from './repositories/Account.repository';
import { IFilterMeta } from '@/interfaces/Model'; import { IFilterMeta } from '@/interfaces/Model';
import { TenantModelProxy } from '../System/models/TenantBaseModel'; import { TenantModelProxy } from '../System/models/TenantBaseModel';
import { GetAccountsQueryDto } from './dtos/GetAccountsQuery.dto';
@Injectable() @Injectable()
export class GetAccountsService { export class GetAccountsService {
@@ -18,7 +19,7 @@ export class GetAccountsService {
@Inject(Account.name) @Inject(Account.name)
private readonly accountModel: TenantModelProxy<typeof Account>, private readonly accountModel: TenantModelProxy<typeof Account>,
) {} ) { }
/** /**
* Retrieve accounts datatable list. * Retrieve accounts datatable list.
@@ -26,12 +27,12 @@ export class GetAccountsService {
* @returns {Promise<{ accounts: IAccountResponse[]; filterMeta: IFilterMeta }>} * @returns {Promise<{ accounts: IAccountResponse[]; filterMeta: IFilterMeta }>}
*/ */
public async getAccountsList( public async getAccountsList(
filterDto: Partial<IAccountsFilter>, filterDto: Partial<GetAccountsQueryDto>,
): Promise<{ accounts: Account[]; filterMeta: IFilterMeta }> { ): Promise<{ accounts: Account[]; filterMeta: IFilterMeta }> {
const parsedFilterDto = { const parsedFilterDto = {
sortOrder: 'desc', sortOrder: 'desc',
columnSortBy: 'created_at', columnSortBy: 'created_at',
inactiveMode: false, onlyInactive: false,
structure: IAccountsStructureType.Tree, structure: IAccountsStructureType.Tree,
...filterDto, ...filterDto,
}; };
@@ -48,7 +49,7 @@ export class GetAccountsService {
.query() .query()
.onBuild((builder) => { .onBuild((builder) => {
dynamicList.buildQuery()(builder); dynamicList.buildQuery()(builder);
builder.modify('inactiveMode', filter.inactiveMode); builder.modify('inactiveMode', filterDto.onlyInactive);
}); });
const accountsGraph = await this.accountRepository.getDependencyGraph(); const accountsGraph = await this.accountRepository.getDependencyGraph();
@@ -58,7 +59,6 @@ export class GetAccountsService {
new AccountTransformer(), new AccountTransformer(),
{ accountsGraph, structure: parsedFilterDto.structure }, { accountsGraph, structure: parsedFilterDto.structure },
); );
return { return {
accounts: transformedAccounts, accounts: transformedAccounts,
filterMeta: dynamicList.getResponseMeta(), filterMeta: dynamicList.getResponseMeta(),

View File

@@ -0,0 +1,27 @@
import { IsBoolean, IsEnum, IsOptional } from 'class-validator';
import { ApiPropertyOptional } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
import { parseBoolean } from '@/utils/parse-boolean';
import { IAccountsStructureType } from '../Accounts.types';
export class GetAccountsQueryDto {
@ApiPropertyOptional({
type: Boolean,
description: 'Filter to show only inactive accounts',
default: false,
})
@IsOptional()
@IsBoolean()
@Transform(({ value }) => parseBoolean(value, false))
onlyInactive?: boolean;
@ApiPropertyOptional({
enum: IAccountsStructureType,
description: 'Structure type for the accounts list',
default: IAccountsStructureType.Tree,
})
@IsOptional()
@IsEnum(IAccountsStructureType)
structure?: IAccountsStructureType;
}

View File

@@ -131,6 +131,6 @@ export const rowClassNames = (row) => ({
export const transformAccountsStateToQuery = (tableState) => { export const transformAccountsStateToQuery = (tableState) => {
return { return {
...transformTableStateToQuery(tableState), ...transformTableStateToQuery(tableState),
inactive_mode: tableState.inactiveMode, onlyInactive: tableState.inactiveMode,
}; };
}; };