feat(SPG-5) Filter

master
ashar 2024-05-30 09:36:20 +07:00
parent 5684bfdcbf
commit e78d1c90d1
3 changed files with 195 additions and 0 deletions

View File

@ -0,0 +1,63 @@
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>,
private readonly table: string,
private readonly params: Param[],
) {}
getFilter() {
const params = this.params?.filter((item) => {
return item.data !== undefined;
});
return this.bySearch(this.query, params);
}
bySearch(query: SelectQueryBuilder<Entity>, params: Param[]) {
query.andWhere(
new Brackets((qb) => {
params.forEach((param) => {
const { cols, data, additional, leftJoin } = param;
const arr = data?.map((el) =>
el.includes("'")
? `'%${el.trim().replace(/'/g, "''").replace(/\s+/g, ' ')}%'`
: `'%${el.trim().replace(/\s+/g, ' ')}%'`,
);
const aliases = !cols.match(/\./g)
? this.table.concat(`.${cols}`)
: cols;
qb['andWhere'](`${aliases} ILIKE ANY(ARRAY[${arr}])`);
if (additional?.length > 0) {
qb['orWhere'](
new Brackets((subQb) => {
for (const addition of additional) {
subQb['orWhere'](`${addition}`);
}
}),
);
}
if (leftJoin?.length) {
for (const join of leftJoin) {
qb['leftJoinAndSelect'](`${join.relations}`, `${join.alias}`);
}
}
});
}),
);
return query;
}
}

View File

@ -0,0 +1,18 @@
import { ORDER_TYPE, STATUS } from "src/core/strings/constants/base.constants";
export interface BaseFilterEntity {
page: number;
limit: number;
q?: string;
names: string[];
entity_ids: string[];
order_by: string;
order_type: ORDER_TYPE;
statuses: STATUS[];
created_ids: string[];
created_from: number;
created_to: number;
updated_ids: string[];
updated_from: number;
updated_to: number;
}

View File

@ -0,0 +1,114 @@
import { ApiProperty } from "@nestjs/swagger";
import { BaseFilterEntity } from "../../domain/entities/base-filter.entity";
import { Transform } from "class-transformer";
import { IsArray, IsEnum, IsNumber, IsString, ValidateIf } from "class-validator";
import { ORDER_TYPE, STATUS } from "src/core/strings/constants/base.constants";
export class BaseFilterDto implements BaseFilterEntity {
@ApiProperty({ type: Number, required: false, default: 1 })
@Transform((body) => Number(body.value))
@ValidateIf((body) => body.page)
@IsNumber()
page = 1;
@ApiProperty({ type: Number, required: false, default: 10 })
@Transform((body) => Number(body.value))
@ValidateIf((body) => body.limit)
@IsNumber()
limit = 10;
@ApiProperty({ type: String, required: false })
q: string;
@ApiProperty({ type: ['string'], required: false })
@Transform((body) => {
return Array.isArray(body.value) ? body.value : [body.value];
})
names: string[];
@ApiProperty({ type: String, required: false })
order_by: string;
@ApiProperty({
type: 'string',
required: false,
description: `Select ("${ORDER_TYPE.ASC}", "${ORDER_TYPE.DESC}")`,
})
@ValidateIf((body) => body.order_type)
@IsEnum(ORDER_TYPE, {
message: `order_type must be a valid enum ${JSON.stringify(
Object.values(ORDER_TYPE),
)}`,
})
order_type: ORDER_TYPE;
@ApiProperty({
type: ['string'],
required: false,
description: `Select ["${STATUS.ACTIVE}"]`,
})
@Transform((body) => {
return Array.isArray(body.value) ? body.value : [body.value];
})
@ValidateIf((body) => {
return body.status;
})
@IsArray()
@IsString({ each: true })
@IsEnum(STATUS, {
message: `Status must be a valid enum ${JSON.stringify(
Object.values(STATUS),
)}`,
each: true,
})
statuses: STATUS[];
@ApiProperty({ type: [String], required: false })
@Transform((body) => {
return Array.isArray(body.value) ? body.value : [body.value];
})
@ValidateIf((body) => body.created_ids)
@IsArray()
@IsString({ each: true })
created_ids: string[];
@ApiProperty({ type: 'integer', required: false })
@ValidateIf((body) => body.created_from)
created_from: number;
@ApiProperty({ type: 'integer', required: false })
@ValidateIf((body) => body.created_to)
created_to: number;
@ApiProperty({ type: [String], required: false })
@Transform((body) => {
return Array.isArray(body.value) ? body.value : [body.value];
})
@ValidateIf((body) => body.updated_ids)
@IsArray()
@IsString({ each: true })
updated_ids: string[];
@ApiProperty({ type: 'integer', required: false })
@Transform((body) => {
return typeof body.value == 'string' ? Number(body.value) : body.value;
})
@ValidateIf((body) => body.updated_from)
updated_from: number;
@ApiProperty({ type: 'integer', required: false })
@Transform((body) => {
return typeof body.value == 'string' ? Number(body.value) : body.value;
})
@ValidateIf((body) => body.updated_to)
updated_to: number;
@ApiProperty({ type: [String], required: false })
@Transform((body) => {
return Array.isArray(body.value) ? body.value : [body.value];
})
@ValidateIf((body) => body.entity_ids)
@IsArray()
@IsString({ each: true })
entity_ids: string[];
}