diff --git a/src/core/helpers/query/between-query.helper.ts b/src/core/helpers/query/between-query.helper.ts new file mode 100644 index 0000000..d056e3f --- /dev/null +++ b/src/core/helpers/query/between-query.helper.ts @@ -0,0 +1,22 @@ +import { SelectQueryBuilder } from 'typeorm'; + +export class BetweenQueryHelper { + constructor( + protected baseQuery: SelectQueryBuilder, + protected moduleName: string, + protected columnName: string, + protected from: any, + protected to: any, + protected valueAlias: string, + ) {} + + getQuery(): SelectQueryBuilder { + return this.baseQuery.andWhere( + `${this.moduleName}.${this.columnName} BETWEEN :from${this.valueAlias} AND :to${this.valueAlias}`, + { + [`from${this.valueAlias}`]: this.from, + [`to${this.valueAlias}`]: this.to, + }, + ); + } +} diff --git a/src/core/helpers/query/default-filter.helper.ts b/src/core/helpers/query/default-filter.helper.ts new file mode 100644 index 0000000..16171ed --- /dev/null +++ b/src/core/helpers/query/default-filter.helper.ts @@ -0,0 +1,84 @@ +import { SelectQueryBuilder } from 'typeorm'; +import { WhereInQueryHelper } from './or-where-in-query.helpe'; +import { BaseFilterEntity } from 'src/core/modules/domain/entities/base-filter.entity'; +import { BetweenQueryHelper } from './between-query.helper'; +import { TABLE_NAME } from 'src/core/strings/constants/table.constants'; +import { ORDER_TYPE } from 'src/core/strings/constants/base.constants'; + +export function setQueryFilterDefault( + queryBuilder: SelectQueryBuilder, + baseFilter: BaseFilterEntity, + tableName: TABLE_NAME, +): SelectQueryBuilder { + // filter berdasarkan statuses + if (!!baseFilter.statuses) + new WhereInQueryHelper( + queryBuilder, + tableName, + 'status', + baseFilter.statuses, + 'statuses', + ).getQuery(); + + // filter berdasarkan id pembuat + if (!!baseFilter.created_ids) + new WhereInQueryHelper( + queryBuilder, + tableName, + 'created_id', + baseFilter.created_ids, + 'created_ids', + ).getQuery(); + + // filter berdasarkan tanggal terakhir dibuat + if (!!baseFilter.created_from && !!baseFilter.created_to) + new BetweenQueryHelper( + queryBuilder, + tableName, + 'created_at', + baseFilter.created_from, + baseFilter.created_to, + 'created', + ).getQuery(); + + // filter berdasarkan id pengubah + if (!!baseFilter.updated_ids) + new WhereInQueryHelper( + queryBuilder, + tableName, + 'editor_id', + baseFilter.updated_ids, + 'editor_ids', + ).getQuery(); + + // filter berdasarkan tanggal terakhir update + if (!!baseFilter.updated_from && !!baseFilter.updated_to) + new BetweenQueryHelper( + queryBuilder, + tableName, + 'updated_at', + baseFilter.updated_from, + baseFilter.updated_to, + 'updated', + ).getQuery(); + + return queryBuilder; +} + +export function getOrderBy( + baseFilter: BaseFilterEntity, + queryBuilder: SelectQueryBuilder, + tableName: TABLE_NAME, +) { + let orderBy: string = `${tableName}.created_at`; + const orderType = baseFilter.order_type ?? ORDER_TYPE.DESC; + + if (!!baseFilter.order_by) { + orderBy = + baseFilter.order_by.split('.').length > 1 + ? `${baseFilter.order_by}` + : `${tableName}.${baseFilter.order_by}`; + } + + queryBuilder.orderBy(orderBy, orderType); +} diff --git a/src/core/helpers/query/join-relations.helper.ts b/src/core/helpers/query/join-relations.helper.ts new file mode 100644 index 0000000..1043e3a --- /dev/null +++ b/src/core/helpers/query/join-relations.helper.ts @@ -0,0 +1,31 @@ +import { TABLE_NAME } from 'src/core/strings/constants/table.constants'; +import { SelectQueryBuilder } from 'typeorm'; + +export function joinRelationHelper( + relations: string[], + tableName: TABLE_NAME, + queryBuilder: SelectQueryBuilder, + type?: string, +) { + relations.forEach((relation) => { + let alias = relation; + let relationName = `${tableName}.${relation}`; + + if (relation.split(' ').length > 1) { + alias = relation.split(' ').pop(); + const relationpath = relation.split(' ')[0]; + + if (relationpath.split('.').length > 1) relationName = relationpath; + else relationName = `${tableName}.${relation.split(' ')[0]}`; + } else if (relation.split('.').length > 1) { + alias = relation.split('.').pop(); + relationName = relation; + } + + if (type == 'count') + queryBuilder.loadRelationCountAndMap(relationName, relationName, alias); + else if (type == 'select') + queryBuilder.leftJoinAndSelect(relationName, alias); + else queryBuilder.leftJoin(relationName, alias); + }); +} diff --git a/src/core/helpers/query/or-where-in-query.helpe.ts b/src/core/helpers/query/or-where-in-query.helpe.ts new file mode 100644 index 0000000..6841fa3 --- /dev/null +++ b/src/core/helpers/query/or-where-in-query.helpe.ts @@ -0,0 +1,20 @@ +import { SelectQueryBuilder } from 'typeorm'; + +export class WhereInQueryHelper { + constructor( + protected baseQuery: SelectQueryBuilder, + protected moduleName: string, + protected columnName: string, + protected values: string[], + protected valueAliases: string, + ) {} + + getQuery(): SelectQueryBuilder { + return this.baseQuery.andWhere( + `${this.moduleName}.${this.columnName} IN (:...${this.valueAliases})`, + { + [this.valueAliases]: this.values, + }, + ); + } +} diff --git a/src/core/helpers/query/search-query.helper.ts b/src/core/helpers/query/search-query.helper.ts new file mode 100644 index 0000000..7ab9c55 --- /dev/null +++ b/src/core/helpers/query/search-query.helper.ts @@ -0,0 +1,20 @@ +import { SelectQueryBuilder } from 'typeorm'; + +export class SearchQueryHelper { + constructor( + protected baseQuery: SelectQueryBuilder, + protected moduleName: string, + protected columnName: string, + protected value: string, + protected valueAliases: string, + ) {} + + getQuery(): SelectQueryBuilder { + return this.baseQuery.andWhere( + `${this.moduleName}.${this.columnName} ILIKE :${this.valueAliases}`, + { + [this.valueAliases]: `%${this.value}%`, + }, + ); + } +} diff --git a/src/core/helpers/query/specific-search.helper.ts b/src/core/helpers/query/specific-search.helper.ts index e1645b4..6ad02d0 100644 --- a/src/core/helpers/query/specific-search.helper.ts +++ b/src/core/helpers/query/specific-search.helper.ts @@ -1,12 +1,6 @@ +import { Param } from 'src/core/modules/domain/entities/base-filter.entity'; import { Brackets, SelectQueryBuilder } from 'typeorm'; -export interface Param { - cols: string; - data: string[]; - additional?: any[]; - leftJoin?: any[]; -} - export class SpecificSearchFilter { constructor( private query: SelectQueryBuilder, diff --git a/src/core/modules/domain/entities/base-filter.entity.ts b/src/core/modules/domain/entities/base-filter.entity.ts index b6581b2..357412d 100644 --- a/src/core/modules/domain/entities/base-filter.entity.ts +++ b/src/core/modules/domain/entities/base-filter.entity.ts @@ -16,3 +16,16 @@ export interface BaseFilterEntity { updated_from: number; updated_to: number; } + +export interface Param { + cols: string; + data: string[]; + additional?: any[]; + leftJoin?: any[]; +} + +export interface RelationParam { + joinRelations: string[]; + selectRelations: string[]; + countRelations: string[]; +} diff --git a/src/core/modules/domain/usecase/base-read.manager.ts b/src/core/modules/domain/usecase/base-read.manager.ts index f987e61..4fd4f61 100644 --- a/src/core/modules/domain/usecase/base-read.manager.ts +++ b/src/core/modules/domain/usecase/base-read.manager.ts @@ -2,6 +2,7 @@ import { Inject, Injectable, Logger } from '@nestjs/common'; import { UserProvider, UsersSession } from 'src/core/sessions'; import { BLANK_USER } from 'src/core/strings/constants/base.constants'; import { TABLE_NAME } from 'src/core/strings/constants/table.constants'; +import { RelationParam } from '../entities/base-filter.entity'; @Injectable() export abstract class BaseReadManager { @@ -9,6 +10,8 @@ export abstract class BaseReadManager { public dataService: any; public queryBuilder: any; protected tableName: TABLE_NAME; + abstract get relations(): RelationParam; + abstract get selects(): string[]; @Inject() protected userProvider: UserProvider; @@ -22,8 +25,9 @@ export abstract class BaseReadManager { } } - setService(dataService) { + setService(dataService, tableName) { this.dataService = dataService; + this.tableName = tableName; this.queryBuilder = this.dataService .getRepository() .createQueryBuilder(this.tableName); diff --git a/src/core/modules/domain/usecase/managers/base-detail.manager.ts b/src/core/modules/domain/usecase/managers/base-detail.manager.ts index 87c8916..86f7742 100644 --- a/src/core/modules/domain/usecase/managers/base-detail.manager.ts +++ b/src/core/modules/domain/usecase/managers/base-detail.manager.ts @@ -1,11 +1,9 @@ +import { joinRelationHelper } from 'src/core/helpers/query/join-relations.helper'; import { BaseReadManager } from '../base-read.manager'; export abstract class BaseDetailManager extends BaseReadManager { protected dataId: string; protected result: Entity; - - abstract get selectData(): string[]; - abstract get relationData(): string[]; abstract get setFindProperties(): any; setData(dataId: string): void { @@ -13,7 +11,26 @@ export abstract class BaseDetailManager extends BaseReadManager { } async process(): Promise { - this.queryBuilder.select(this.selectData).where(this.setFindProperties); + const { joinRelations, selectRelations, countRelations } = this.relations; + if (joinRelations?.length) + joinRelationHelper(joinRelations, this.tableName, this.queryBuilder); + if (selectRelations?.length) + joinRelationHelper( + selectRelations, + this.tableName, + this.queryBuilder, + 'select', + ); + if (countRelations?.length) + joinRelationHelper( + countRelations, + this.tableName, + this.queryBuilder, + 'count', + ); + + if (this.selects?.length) this.queryBuilder.select(this.selects); + this.queryBuilder.where(this.setFindProperties); this.result = await this.queryBuilder.getOne(); } diff --git a/src/core/modules/domain/usecase/managers/base-index.manager.ts b/src/core/modules/domain/usecase/managers/base-index.manager.ts index db6eff5..9c757fa 100644 --- a/src/core/modules/domain/usecase/managers/base-index.manager.ts +++ b/src/core/modules/domain/usecase/managers/base-index.manager.ts @@ -1,10 +1,13 @@ import { PaginationResponse } from 'src/core/response/domain/ok-response.interface'; import { BaseReadManager } from '../base-read.manager'; import { SelectQueryBuilder } from 'typeorm'; +import { SpecificSearchFilter } from 'src/core/helpers/query/specific-search.helper'; import { - Param, - SpecificSearchFilter, -} from 'src/core/helpers/query/specific-search.helper'; + getOrderBy, + setQueryFilterDefault, +} from 'src/core/helpers/query/default-filter.helper'; +import { Param } from '../../entities/base-filter.entity'; +import { joinRelationHelper } from 'src/core/helpers/query/join-relations.helper'; export abstract class BaseIndexManager extends BaseReadManager { protected result: PaginationResponse; @@ -16,26 +19,36 @@ export abstract class BaseIndexManager extends BaseReadManager { } async process(): Promise { - // const filterSearch: string[] = this.setFilterSearch(); + const { joinRelations, selectRelations, countRelations } = this.relations; - // this.queryBuilder.andWhere( - // new Brackets((qb) => { - // filterSearch.map((fSearch) => { - // qb.orWhere(`${fSearch} ILIKE :query`, { - // query: `%${ - // this.filterParam.q.trim().replace(/\s+/g, ' ') ?? '' - // }%`, - // }); - // }); - // }), - // ); + if (joinRelations?.length) + joinRelationHelper(joinRelations, this.tableName, this.queryBuilder); + if (selectRelations?.length) + joinRelationHelper( + selectRelations, + this.tableName, + this.queryBuilder, + 'select', + ); + if (countRelations?.length) + joinRelationHelper( + countRelations, + this.tableName, + this.queryBuilder, + 'count', + ); - // new SpecificSearchFilter( - // this.queryBuilder, - // this.tableName, - // this.specificFilter, - // ).getFilter(); + if (this.selects?.length) this.queryBuilder.select(this.selects); + + new SpecificSearchFilter( + this.queryBuilder, + this.tableName, + this.specificFilter, + ).getFilter(); + + getOrderBy(this.filterParam, this.queryBuilder, this.tableName); this.setQueryFilter(this.queryBuilder); + setQueryFilterDefault(this.queryBuilder, this.filterParam, this.tableName); this.result = await this.dataService.getIndex( this.queryBuilder, @@ -43,10 +56,6 @@ export abstract class BaseIndexManager extends BaseReadManager { ); } - setFilterSearch(): string[] { - return []; - } - abstract setQueryFilter( queryBuilder: SelectQueryBuilder, ): SelectQueryBuilder; diff --git a/src/core/modules/infrastructure/dto/base-filter.dto.ts b/src/core/modules/infrastructure/dto/base-filter.dto.ts index 9e4bf24..f9d9ec4 100644 --- a/src/core/modules/infrastructure/dto/base-filter.dto.ts +++ b/src/core/modules/infrastructure/dto/base-filter.dto.ts @@ -23,7 +23,6 @@ export class BaseFilterDto implements BaseFilterEntity { @IsNumber() limit = 10; - @ApiProperty({ type: String, required: false }) q: string; @ApiProperty({ type: ['string'], required: false }) diff --git a/src/modules/configuration/auth/domain/managers/login.manager.ts b/src/modules/configuration/auth/domain/managers/login.manager.ts index 0f64799..fe15496 100644 --- a/src/modules/configuration/auth/domain/managers/login.manager.ts +++ b/src/modules/configuration/auth/domain/managers/login.manager.ts @@ -32,6 +32,7 @@ export class LoginManager extends BaseCustomManager { username: this.data.username, }, }); + if (!this.userLogin) this.throwError(); const valid = await validatePassword( this.data.password, @@ -47,7 +48,6 @@ export class LoginManager extends BaseCustomManager { user_privilege_id: this.userLogin.user_privilege_id, }; - console.log(this.session, 'das'); this.token = this.session.createAccessToken(tokenData); const refreshToken = this.session.createAccessToken(tokenData); diff --git a/src/modules/user-related/user-privilege/domain/usecases/user-privilege-configuration/managers/index-user-privilege-configuration.manager.ts b/src/modules/user-related/user-privilege/domain/usecases/user-privilege-configuration/managers/index-user-privilege-configuration.manager.ts index d8af159..1095fd9 100644 --- a/src/modules/user-related/user-privilege/domain/usecases/user-privilege-configuration/managers/index-user-privilege-configuration.manager.ts +++ b/src/modules/user-related/user-privilege/domain/usecases/user-privilege-configuration/managers/index-user-privilege-configuration.manager.ts @@ -1,8 +1,11 @@ import { Injectable } from '@nestjs/common'; import { BaseIndexManager } from 'src/core/modules/domain/usecase/managers/base-index.manager'; import { UserPrivilegeConfigurationEntity } from '../../../entities/user-privilege-configuration.entity'; -import { Param } from 'src/core/helpers/query/specific-search.helper'; import { SelectQueryBuilder } from 'typeorm'; +import { + Param, + RelationParam, +} from 'src/core/modules/domain/entities/base-filter.entity'; @Injectable() export class IndexUserPrivilegeConfigurationManager extends BaseIndexManager { @@ -18,6 +21,18 @@ export class IndexUserPrivilegeConfigurationManager extends BaseIndexManager, ): SelectQueryBuilder { - console.log(this.filterParam, 'param'); if (this.filterParam.user_privilege_ids) { queryBuilder.andWhere(`user_privilege_id In (:...privilegeIds)`, { privilegeIds: this.filterParam.user_privilege_ids, diff --git a/src/modules/user-related/user-privilege/domain/usecases/user-privilege-configuration/user-privilege-configuration-data.orchestrator.ts b/src/modules/user-related/user-privilege/domain/usecases/user-privilege-configuration/user-privilege-configuration-data.orchestrator.ts index 966251b..e0d6c09 100644 --- a/src/modules/user-related/user-privilege/domain/usecases/user-privilege-configuration/user-privilege-configuration-data.orchestrator.ts +++ b/src/modules/user-related/user-privilege/domain/usecases/user-privilege-configuration/user-privilege-configuration-data.orchestrator.ts @@ -4,6 +4,7 @@ import { UserPrivilegeConfigurationEntity } from '../../entities/user-privilege- import { UserPrivilegeConfigurationService } from '../../../data/service/user-privilege-configuration.service'; import { IndexUserPrivilegeConfigurationManager } from './managers/index-user-privilege-configuration.manager'; import { PaginationResponse } from 'src/core/response/domain/ok-response.interface'; +import { TABLE_NAME } from 'src/core/strings/constants/table.constants'; @Injectable() export class UserPrivilegeConfigurationDataOrchestrator { @@ -24,7 +25,10 @@ export class UserPrivilegeConfigurationDataOrchestrator { params, ): Promise> { this.indexManager.setFilterParam(params); - this.indexManager.setService(this.serviceData); + this.indexManager.setService( + this.serviceData, + TABLE_NAME.USER_PRIVILEGE_CONFIGURATION, + ); await this.indexManager.execute(); return this.indexManager.getResult(); } diff --git a/src/modules/user-related/user-privilege/domain/usecases/user-privilege/managers/detail-user-privilege.manager.ts b/src/modules/user-related/user-privilege/domain/usecases/user-privilege/managers/detail-user-privilege.manager.ts index 720c366..b5357a0 100644 --- a/src/modules/user-related/user-privilege/domain/usecases/user-privilege/managers/detail-user-privilege.manager.ts +++ b/src/modules/user-related/user-privilege/domain/usecases/user-privilege/managers/detail-user-privilege.manager.ts @@ -2,23 +2,10 @@ import { Injectable } from '@nestjs/common'; import { BaseDetailManager } from 'src/core/modules/domain/usecase/managers/base-detail.manager'; import { UserPrivilegeEntity } from '../../../entities/user-privilege.entity'; import { TABLE_NAME } from 'src/core/strings/constants/table.constants'; +import { RelationParam } from 'src/core/modules/domain/entities/base-filter.entity'; @Injectable() export class DetailUserPrivilegeManager extends BaseDetailManager { - get setFindProperties(): any { - return { - id: this.dataId, - }; - } - - get selectData(): string[] { - return ['id']; - } - - get relationData(): string[] { - return []; - } - async prepareData(): Promise { this.tableName = TABLE_NAME.USER_PRIVILEGE; return; @@ -31,4 +18,22 @@ export class DetailUserPrivilegeManager extends BaseDetailManager { return; } + + get relations(): RelationParam { + return { + joinRelations: [], + selectRelations: [], + countRelations: [], + }; + } + + get selects(): string[] { + return []; + } + + get setFindProperties(): any { + return { + id: this.dataId, + }; + } } diff --git a/src/modules/user-related/user-privilege/domain/usecases/user-privilege/managers/index-user-privilege.manager.ts b/src/modules/user-related/user-privilege/domain/usecases/user-privilege/managers/index-user-privilege.manager.ts index 33b3f20..ee5f965 100644 --- a/src/modules/user-related/user-privilege/domain/usecases/user-privilege/managers/index-user-privilege.manager.ts +++ b/src/modules/user-related/user-privilege/domain/usecases/user-privilege/managers/index-user-privilege.manager.ts @@ -2,13 +2,14 @@ import { Injectable } from '@nestjs/common'; import { BaseIndexManager } from 'src/core/modules/domain/usecase/managers/base-index.manager'; import { UserPrivilegeEntity } from '../../../entities/user-privilege.entity'; import { SelectQueryBuilder } from 'typeorm'; -import { TABLE_NAME } from 'src/core/strings/constants/table.constants'; -import { Param } from 'src/core/helpers/query/specific-search.helper'; +import { + Param, + RelationParam, +} from 'src/core/modules/domain/entities/base-filter.entity'; @Injectable() export class IndexUserPrivilegeManager extends BaseIndexManager { async prepareData(): Promise { - this.tableName = TABLE_NAME.USER_PRIVILEGE; return; } @@ -20,17 +21,30 @@ export class IndexUserPrivilegeManager extends BaseIndexManager, ): SelectQueryBuilder { return queryBuilder; } - - setFilterSearch(): string[] { - return []; - } } diff --git a/src/modules/user-related/user-privilege/domain/usecases/user-privilege/user-privilege-read.orchestrator.ts b/src/modules/user-related/user-privilege/domain/usecases/user-privilege/user-privilege-read.orchestrator.ts index 3e8523c..68f45d6 100644 --- a/src/modules/user-related/user-privilege/domain/usecases/user-privilege/user-privilege-read.orchestrator.ts +++ b/src/modules/user-related/user-privilege/domain/usecases/user-privilege/user-privilege-read.orchestrator.ts @@ -5,6 +5,7 @@ import { UserPrivilegeEntity } from '../../entities/user-privilege.entity'; import { PaginationResponse } from 'src/core/response/domain/ok-response.interface'; import { BaseReadOrchestrator } from 'src/core/modules/domain/usecase/orchestrators/base-read.orchestrator'; import { DetailUserPrivilegeManager } from './managers/detail-user-privilege.manager'; +import { TABLE_NAME } from 'src/core/strings/constants/table.constants'; @Injectable() export class UserPrivilegeReadOrchestrator extends BaseReadOrchestrator { @@ -18,14 +19,14 @@ export class UserPrivilegeReadOrchestrator extends BaseReadOrchestrator> { this.indexManager.setFilterParam(params); - this.indexManager.setService(this.serviceData); + this.indexManager.setService(this.serviceData, TABLE_NAME.USER_PRIVILEGE); await this.indexManager.execute(); return this.indexManager.getResult(); } async detail(dataId: string): Promise { this.detailManager.setData(dataId); - this.detailManager.setService(this.serviceData); + this.detailManager.setService(this.serviceData, TABLE_NAME.USER_PRIVILEGE); await this.detailManager.execute(); return this.detailManager.getResult(); }