feat(SPG-5) Filter

pull/2/head
ashar 2024-06-04 15:52:33 +07:00
parent 1ac5aca57d
commit 6596c776e8
17 changed files with 316 additions and 65 deletions

View File

@ -0,0 +1,22 @@
import { SelectQueryBuilder } from 'typeorm';
export class BetweenQueryHelper {
constructor(
protected baseQuery: SelectQueryBuilder<any>,
protected moduleName: string,
protected columnName: string,
protected from: any,
protected to: any,
protected valueAlias: string,
) {}
getQuery(): SelectQueryBuilder<any> {
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,
},
);
}
}

View File

@ -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<any>,
baseFilter: BaseFilterEntity,
tableName: TABLE_NAME,
): SelectQueryBuilder<any> {
// 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<any>,
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);
}

View File

@ -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<any>,
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);
});
}

View File

@ -0,0 +1,20 @@
import { SelectQueryBuilder } from 'typeorm';
export class WhereInQueryHelper {
constructor(
protected baseQuery: SelectQueryBuilder<any>,
protected moduleName: string,
protected columnName: string,
protected values: string[],
protected valueAliases: string,
) {}
getQuery(): SelectQueryBuilder<any> {
return this.baseQuery.andWhere(
`${this.moduleName}.${this.columnName} IN (:...${this.valueAliases})`,
{
[this.valueAliases]: this.values,
},
);
}
}

View File

@ -0,0 +1,20 @@
import { SelectQueryBuilder } from 'typeorm';
export class SearchQueryHelper {
constructor(
protected baseQuery: SelectQueryBuilder<any>,
protected moduleName: string,
protected columnName: string,
protected value: string,
protected valueAliases: string,
) {}
getQuery(): SelectQueryBuilder<any> {
return this.baseQuery.andWhere(
`${this.moduleName}.${this.columnName} ILIKE :${this.valueAliases}`,
{
[this.valueAliases]: `%${this.value}%`,
},
);
}
}

View File

@ -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<Entity = any> {
constructor(
private query: SelectQueryBuilder<Entity>,

View File

@ -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[];
}

View File

@ -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);

View File

@ -1,11 +1,9 @@
import { joinRelationHelper } from 'src/core/helpers/query/join-relations.helper';
import { BaseReadManager } from '../base-read.manager';
export abstract class BaseDetailManager<Entity> 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<Entity> extends BaseReadManager {
}
async process(): Promise<void> {
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();
}

View File

@ -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<Entity> extends BaseReadManager {
protected result: PaginationResponse<Entity>;
@ -16,26 +19,36 @@ export abstract class BaseIndexManager<Entity> extends BaseReadManager {
}
async process(): Promise<void> {
// 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<Entity>(
// this.queryBuilder,
// this.tableName,
// this.specificFilter,
// ).getFilter();
if (this.selects?.length) this.queryBuilder.select(this.selects);
new SpecificSearchFilter<Entity>(
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<Entity> extends BaseReadManager {
);
}
setFilterSearch(): string[] {
return [];
}
abstract setQueryFilter(
queryBuilder: SelectQueryBuilder<Entity>,
): SelectQueryBuilder<Entity>;

View File

@ -23,7 +23,6 @@ export class BaseFilterDto implements BaseFilterEntity {
@IsNumber()
limit = 10;
@ApiProperty({ type: String, required: false })
q: string;
@ApiProperty({ type: ['string'], required: false })

View File

@ -32,6 +32,7 @@ export class LoginManager extends BaseCustomManager<UserEntity> {
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<UserEntity> {
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);

View File

@ -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<UserPrivilegeConfigurationEntity> {
@ -18,6 +21,18 @@ export class IndexUserPrivilegeConfigurationManager extends BaseIndexManager<Use
return;
}
get relations(): RelationParam {
return {
joinRelations: [],
selectRelations: [],
countRelations: [],
};
}
get selects(): string[] {
return [];
}
get specificFilter(): Param[] {
return;
}
@ -25,7 +40,6 @@ export class IndexUserPrivilegeConfigurationManager extends BaseIndexManager<Use
setQueryFilter(
queryBuilder: SelectQueryBuilder<UserPrivilegeConfigurationEntity>,
): SelectQueryBuilder<UserPrivilegeConfigurationEntity> {
console.log(this.filterParam, 'param');
if (this.filterParam.user_privilege_ids) {
queryBuilder.andWhere(`user_privilege_id In (:...privilegeIds)`, {
privilegeIds: this.filterParam.user_privilege_ids,

View File

@ -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<PaginationResponse<UserPrivilegeConfigurationEntity>> {
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();
}

View File

@ -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<UserPrivilegeEntity> {
get setFindProperties(): any {
return {
id: this.dataId,
};
}
get selectData(): string[] {
return ['id'];
}
get relationData(): string[] {
return [];
}
async prepareData(): Promise<void> {
this.tableName = TABLE_NAME.USER_PRIVILEGE;
return;
@ -31,4 +18,22 @@ export class DetailUserPrivilegeManager extends BaseDetailManager<UserPrivilegeE
async afterProcess(): Promise<void> {
return;
}
get relations(): RelationParam {
return {
joinRelations: [],
selectRelations: [],
countRelations: [],
};
}
get selects(): string[] {
return [];
}
get setFindProperties(): any {
return {
id: this.dataId,
};
}
}

View File

@ -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<UserPrivilegeEntity> {
async prepareData(): Promise<void> {
this.tableName = TABLE_NAME.USER_PRIVILEGE;
return;
}
@ -20,17 +21,30 @@ export class IndexUserPrivilegeManager extends BaseIndexManager<UserPrivilegeEnt
return;
}
get specificFilter(): Param[] {
get relations(): RelationParam {
return {
joinRelations: [],
selectRelations: [],
countRelations: [],
};
}
get selects(): string[] {
return [];
}
get specificFilter(): Param[] {
return [
{
cols: `${this.tableName}.name`,
data: this.filterParam.names,
},
];
}
setQueryFilter(
queryBuilder: SelectQueryBuilder<UserPrivilegeEntity>,
): SelectQueryBuilder<UserPrivilegeEntity> {
return queryBuilder;
}
setFilterSearch(): string[] {
return [];
}
}

View File

@ -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<UserPrivilegeEntity> {
@ -18,14 +19,14 @@ export class UserPrivilegeReadOrchestrator extends BaseReadOrchestrator<UserPriv
async index(params): Promise<PaginationResponse<UserPrivilegeEntity>> {
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<UserPrivilegeEntity> {
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();
}