From 417e90dbc5cdea6167b00229303f5bc841918dae Mon Sep 17 00:00:00 2001 From: ashar Date: Mon, 10 Jun 2024 14:14:34 +0700 Subject: [PATCH] feat(SPG-325) REST API Read Users --- .../domain/entities/filter-tenant.entity.ts | 2 +- .../managers/detail-tenant.manager.ts | 7 +- .../usecases/managers/index-tenant.manager.ts | 8 +- .../infrastructure/dto/filter-tenant.dto.ts | 7 +- .../domain/entities/filter-user.entity.ts | 10 +++ .../usecases/managers/detail-user.manager.ts | 54 ++++++++++++ .../usecases/managers/index-user.manager.ts | 82 +++++++++++++++++++ .../domain/usecases/user-read.orchestrator.ts | 33 ++++++++ .../infrastructure/dto/filter-user.dto.ts | 26 ++++++ .../infrastructure/user-read.controller.ts | 30 +++++++ 10 files changed, 253 insertions(+), 6 deletions(-) create mode 100644 src/modules/user-related/user/domain/entities/filter-user.entity.ts create mode 100644 src/modules/user-related/user/domain/usecases/managers/detail-user.manager.ts create mode 100644 src/modules/user-related/user/domain/usecases/managers/index-user.manager.ts create mode 100644 src/modules/user-related/user/domain/usecases/user-read.orchestrator.ts create mode 100644 src/modules/user-related/user/infrastructure/dto/filter-user.dto.ts create mode 100644 src/modules/user-related/user/infrastructure/user-read.controller.ts diff --git a/src/modules/user-related/tenant/domain/entities/filter-tenant.entity.ts b/src/modules/user-related/tenant/domain/entities/filter-tenant.entity.ts index e060167..e1c0be0 100644 --- a/src/modules/user-related/tenant/domain/entities/filter-tenant.entity.ts +++ b/src/modules/user-related/tenant/domain/entities/filter-tenant.entity.ts @@ -1,6 +1,6 @@ import { BaseFilterEntity } from 'src/core/modules/domain/entities/base-filter.entity'; -export interface FilterUserEntity extends BaseFilterEntity { +export interface FilterTenantEntity extends BaseFilterEntity { emails: string[]; usernames: string[]; } diff --git a/src/modules/user-related/tenant/domain/usecases/managers/detail-tenant.manager.ts b/src/modules/user-related/tenant/domain/usecases/managers/detail-tenant.manager.ts index 4387dce..0b76919 100644 --- a/src/modules/user-related/tenant/domain/usecases/managers/detail-tenant.manager.ts +++ b/src/modules/user-related/tenant/domain/usecases/managers/detail-tenant.manager.ts @@ -19,8 +19,13 @@ export class DetailTenantManager extends BaseDetailManager { get relations(): RelationParam { return { + // relation only join (for query purpose) joinRelations: [], - selectRelations: [], + + // relation join and select (relasi yang ingin ditampilkan), + selectRelations: [''], + + // relation yang hanya ingin dihitung (akan return number) countRelations: [], }; } diff --git a/src/modules/user-related/tenant/domain/usecases/managers/index-tenant.manager.ts b/src/modules/user-related/tenant/domain/usecases/managers/index-tenant.manager.ts index 63dba64..94d77e9 100644 --- a/src/modules/user-related/tenant/domain/usecases/managers/index-tenant.manager.ts +++ b/src/modules/user-related/tenant/domain/usecases/managers/index-tenant.manager.ts @@ -24,8 +24,13 @@ export class IndexTenantManager extends BaseIndexManager { get relations(): RelationParam { return { + // relation only join (for query purpose) joinRelations: [], - selectRelations: [], + + // relation join and select (relasi yang ingin ditampilkan), + selectRelations: [''], + + // relation yang hanya ingin dihitung (akan return number) countRelations: [], }; } @@ -65,7 +70,6 @@ export class IndexTenantManager extends BaseIndexManager { setQueryFilter( queryBuilder: SelectQueryBuilder, ): SelectQueryBuilder { - // tampilkan hanya role tenant // ? karena menggunakan table user (admin, staff, tenant) queryBuilder.andWhere(`${this.tableName}.role = :tenant`, { diff --git a/src/modules/user-related/tenant/infrastructure/dto/filter-tenant.dto.ts b/src/modules/user-related/tenant/infrastructure/dto/filter-tenant.dto.ts index 47068a4..056726e 100644 --- a/src/modules/user-related/tenant/infrastructure/dto/filter-tenant.dto.ts +++ b/src/modules/user-related/tenant/infrastructure/dto/filter-tenant.dto.ts @@ -1,9 +1,12 @@ import { BaseFilterDto } from 'src/core/modules/infrastructure/dto/base-filter.dto'; -import { FilterUserEntity } from '../../domain/entities/filter-tenant.entity'; +import { FilterTenantEntity } from '../../domain/entities/filter-tenant.entity'; import { ApiProperty } from '@nestjs/swagger'; import { Transform } from 'class-transformer'; -export class FilterTenantDto extends BaseFilterDto implements FilterUserEntity { +export class FilterTenantDto + extends BaseFilterDto + implements FilterTenantEntity +{ @ApiProperty({ type: ['string'], required: false }) @Transform((body) => { return Array.isArray(body.value) ? body.value : [body.value]; diff --git a/src/modules/user-related/user/domain/entities/filter-user.entity.ts b/src/modules/user-related/user/domain/entities/filter-user.entity.ts new file mode 100644 index 0000000..8f66f91 --- /dev/null +++ b/src/modules/user-related/user/domain/entities/filter-user.entity.ts @@ -0,0 +1,10 @@ +import { BaseFilterEntity } from 'src/core/modules/domain/entities/base-filter.entity'; + +export interface FilterUserEntity extends BaseFilterEntity { + // for searching + usernames: string[]; + user_privileges: string[]; + + // for filtering + user_privilege_ids: string[]; +} diff --git a/src/modules/user-related/user/domain/usecases/managers/detail-user.manager.ts b/src/modules/user-related/user/domain/usecases/managers/detail-user.manager.ts new file mode 100644 index 0000000..7e28045 --- /dev/null +++ b/src/modules/user-related/user/domain/usecases/managers/detail-user.manager.ts @@ -0,0 +1,54 @@ +import { Injectable } from '@nestjs/common'; +import { BaseDetailManager } from 'src/core/modules/domain/usecase/managers/base-detail.manager'; +import { UserEntity } from '../../entities/user.entity'; +import { RelationParam } from 'src/core/modules/domain/entities/base-filter.entity'; + +@Injectable() +export class DetailUserManager extends BaseDetailManager { + async prepareData(): Promise { + return; + } + + async beforeProcess(): Promise { + return; + } + + async afterProcess(): Promise { + return; + } + + get relations(): RelationParam { + return { + // relation only join (for query purpose) + joinRelations: [], + + // relation join and select (relasi yang ingin ditampilkan), + selectRelations: ['user_privilege'], + + // relation yang hanya ingin dihitung (akan return number) + countRelations: [], + }; + } + + get selects(): string[] { + return [ + `${this.tableName}.id`, + `${this.tableName}.status`, + `${this.tableName}.name`, + `${this.tableName}.username`, + `${this.tableName}.created_at`, + `${this.tableName}.creator_name`, + `${this.tableName}.updated_at`, + `${this.tableName}.editor_name`, + + 'user_privilege.id', + 'user_privilege.name', + ]; + } + + get setFindProperties(): any { + return { + id: this.dataId, + }; + } +} diff --git a/src/modules/user-related/user/domain/usecases/managers/index-user.manager.ts b/src/modules/user-related/user/domain/usecases/managers/index-user.manager.ts new file mode 100644 index 0000000..1d6869c --- /dev/null +++ b/src/modules/user-related/user/domain/usecases/managers/index-user.manager.ts @@ -0,0 +1,82 @@ +import { Injectable } from '@nestjs/common'; +import { BaseIndexManager } from 'src/core/modules/domain/usecase/managers/base-index.manager'; +import { UserEntity } from '../../entities/user.entity'; +import { SelectQueryBuilder } from 'typeorm'; +import { + Param, + RelationParam, +} from 'src/core/modules/domain/entities/base-filter.entity'; +import { UserRole } from '../../../constants'; + +@Injectable() +export class IndexUserManager extends BaseIndexManager { + async prepareData(): Promise { + return; + } + + async beforeProcess(): Promise { + return; + } + + async afterProcess(): Promise { + return; + } + + get relations(): RelationParam { + return { + // relation only join (for query purpose) + joinRelations: [], + + // relation join and select (relasi yang ingin ditampilkan), + selectRelations: ['user_privilege'], + + // relation yang hanya ingin dihitung (akan return number) + countRelations: [], + }; + } + + get selects(): string[] { + return [ + `${this.tableName}.id`, + `${this.tableName}.status`, + `${this.tableName}.name`, + `${this.tableName}.username`, + `${this.tableName}.created_at`, + `${this.tableName}.creator_name`, + `${this.tableName}.updated_at`, + `${this.tableName}.editor_name`, + + 'user_privilege.id', + 'user_privilege.name', + ]; + } + + get specificFilter(): Param[] { + return [ + { + cols: `${this.tableName}.name`, + data: this.filterParam.names, + }, + { + cols: `${this.tableName}.username`, + data: this.filterParam.usernames, + }, + { + cols: `user_privilege.name`, + data: this.filterParam.user_privileges, + }, + ]; + } + + setQueryFilter( + queryBuilder: SelectQueryBuilder, + ): SelectQueryBuilder { + // jangan tampilkan role tenant + // ? karena menggunakan table user (admin, staff, tenant) + queryBuilder.andWhere(`${this.tableName}.role != :tenant`, { + tenant: UserRole.TENANT, + }); + + return queryBuilder; + } +} diff --git a/src/modules/user-related/user/domain/usecases/user-read.orchestrator.ts b/src/modules/user-related/user/domain/usecases/user-read.orchestrator.ts new file mode 100644 index 0000000..1a6b01b --- /dev/null +++ b/src/modules/user-related/user/domain/usecases/user-read.orchestrator.ts @@ -0,0 +1,33 @@ +import { Injectable } from '@nestjs/common'; +import { IndexUserManager } from './managers/index-user.manager'; +import { UserReadService } from '../../data/services/user-read.service'; +import { UserEntity } from '../entities/user.entity'; +import { PaginationResponse } from 'src/core/response/domain/ok-response.interface'; +import { BaseReadOrchestrator } from 'src/core/modules/domain/usecase/orchestrators/base-read.orchestrator'; +import { DetailUserManager } from './managers/detail-user.manager'; +import { TABLE_NAME } from 'src/core/strings/constants/table.constants'; + +@Injectable() +export class UserReadOrchestrator extends BaseReadOrchestrator { + constructor( + private indexManager: IndexUserManager, + private detailManager: DetailUserManager, + private serviceData: UserReadService, + ) { + super(); + } + + async index(params): Promise> { + this.indexManager.setFilterParam(params); + this.indexManager.setService(this.serviceData, TABLE_NAME.USER); + await this.indexManager.execute(); + return this.indexManager.getResult(); + } + + async detail(dataId: string): Promise { + this.detailManager.setData(dataId); + this.detailManager.setService(this.serviceData, TABLE_NAME.USER); + await this.detailManager.execute(); + return this.detailManager.getResult(); + } +} diff --git a/src/modules/user-related/user/infrastructure/dto/filter-user.dto.ts b/src/modules/user-related/user/infrastructure/dto/filter-user.dto.ts new file mode 100644 index 0000000..9849477 --- /dev/null +++ b/src/modules/user-related/user/infrastructure/dto/filter-user.dto.ts @@ -0,0 +1,26 @@ +import { BaseFilterDto } from 'src/core/modules/infrastructure/dto/base-filter.dto'; +import { FilterUserEntity } from '../../domain/entities/filter-user.entity'; +import { ApiProperty } from '@nestjs/swagger'; +import { Transform } from 'class-transformer'; + +export class FilterUserDto extends BaseFilterDto implements FilterUserEntity { + // for searching + @ApiProperty({ type: ['string'], required: false }) + @Transform((body) => { + return Array.isArray(body.value) ? body.value : [body.value]; + }) + usernames: string[]; + + @ApiProperty({ type: ['string'], required: false }) + @Transform((body) => { + return Array.isArray(body.value) ? body.value : [body.value]; + }) + user_privileges: string[]; + + // for filtering + @ApiProperty({ type: ['string'], required: false }) + @Transform((body) => { + return Array.isArray(body.value) ? body.value : [body.value]; + }) + user_privilege_ids: string[]; +} diff --git a/src/modules/user-related/user/infrastructure/user-read.controller.ts b/src/modules/user-related/user/infrastructure/user-read.controller.ts new file mode 100644 index 0000000..f3bd23e --- /dev/null +++ b/src/modules/user-related/user/infrastructure/user-read.controller.ts @@ -0,0 +1,30 @@ +import { Controller, Get, Param, Query } from '@nestjs/common'; +import { FilterUserDto } from './dto/filter-user.dto'; +import { Pagination } from 'src/core/response'; +import { PaginationResponse } from 'src/core/response/domain/ok-response.interface'; +import { UserEntity } from '../domain/entities/user.entity'; +import { UserReadOrchestrator } from '../domain/usecases/user-read.orchestrator'; +import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; +import { MODULE_NAME } from 'src/core/strings/constants/module.constants'; +import { Public } from 'src/core/guards'; + +@ApiTags(`${MODULE_NAME.USER.split('-').join(' ')} - read`) +@Controller(MODULE_NAME.USER) +@Public(false) +@ApiBearerAuth('JWT') +export class UserReadController { + constructor(private orchestrator: UserReadOrchestrator) {} + + @Get() + @Pagination() + async index( + @Query() params: FilterUserDto, + ): Promise> { + return await this.orchestrator.index(params); + } + + @Get(':id') + async detail(@Param('id') id: string): Promise { + return await this.orchestrator.detail(id); + } +}