feat: mejorar la búsqueda de auditoría al agregar soporte para filtros y ordenamiento
This commit is contained in:
parent
ce9f9029e3
commit
fb7d3f7043
@ -1,5 +1,5 @@
|
||||
import type { AuditValue } from "@repo/rdx-audit";
|
||||
import type { Criteria } from "@repo/rdx-criteria/server";
|
||||
import type { Criteria, FiltersPrimitives } from "@repo/rdx-criteria/server";
|
||||
import { Op, Sequelize } from "sequelize";
|
||||
|
||||
import { AuditChangeModel, AuditEventModel } from "./sequelize";
|
||||
@ -59,6 +59,7 @@ export interface IAuditReader {
|
||||
search(query: AuditSearchQuery, access: AuditReadAccess): Promise<AuditSearchResult>;
|
||||
findById(id: string, access: AuditReadAccess): Promise<AuditDetail | null>;
|
||||
}
|
||||
|
||||
const FIELD_MAP: Record<string, string> = {
|
||||
occurredAt: "occurred_at",
|
||||
kind: "kind",
|
||||
@ -80,31 +81,10 @@ export class SequelizeAuditReader implements IAuditReader {
|
||||
async search(query: AuditSearchQuery, access: AuditReadAccess): Promise<AuditSearchResult> {
|
||||
const primitives = query.criteria.toPrimitives();
|
||||
const filters = primitives.filters ?? [];
|
||||
this.assertSupportedFilters(filters);
|
||||
|
||||
for (const filter of filters) {
|
||||
if (!FIELD_MAP[filter.field]) throw new Error(`Unsupported audit filter: ${filter.field}`);
|
||||
}
|
||||
|
||||
const orderBy = primitives.orderBy ?? "occurredAt";
|
||||
if (!SORTABLE.has(orderBy)) throw new Error(`Unsupported audit order: ${orderBy}`);
|
||||
|
||||
const where: Record<PropertyKey, unknown> = { ...this.accessWhere(access) };
|
||||
|
||||
for (const filter of filters) {
|
||||
const column = FIELD_MAP[filter.field];
|
||||
if (filter.operator === ">=" || filter.operator === "<") {
|
||||
where[column] = {
|
||||
...(typeof where[column] === "object" && where[column] !== null ? where[column] : {}),
|
||||
[filter.operator === ">=" ? Op.gte : Op.lt]: filter.value,
|
||||
};
|
||||
} else {
|
||||
where[column] = filter.value;
|
||||
}
|
||||
}
|
||||
|
||||
if (query.quickSearch) {
|
||||
where[Op.and] = [{ [Op.or]: this.quickSearch(query.quickSearch) }];
|
||||
}
|
||||
const orderBy = this.resolveOrderBy(primitives.orderBy);
|
||||
const where = this.buildWhere(access, filters, query.quickSearch);
|
||||
|
||||
const pageSize = primitives.pageSize ?? 50;
|
||||
const pageNumber = primitives.pageNumber ?? 0;
|
||||
@ -136,6 +116,51 @@ export class SequelizeAuditReader implements IAuditReader {
|
||||
pageSize,
|
||||
};
|
||||
}
|
||||
|
||||
private assertSupportedFilters(filters: readonly FiltersPrimitives[]): void {
|
||||
for (const filter of filters) {
|
||||
if (!FIELD_MAP[filter.field]) {
|
||||
throw new Error(`Unsupported audit filter: ${filter.field}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private resolveOrderBy(orderBy?: string): string {
|
||||
const resolvedOrderBy = orderBy ?? "occurredAt";
|
||||
if (!SORTABLE.has(resolvedOrderBy)) {
|
||||
throw new Error(`Unsupported audit order: ${resolvedOrderBy}`);
|
||||
}
|
||||
|
||||
return resolvedOrderBy;
|
||||
}
|
||||
|
||||
private buildWhere(
|
||||
access: AuditReadAccess,
|
||||
filters: readonly FiltersPrimitives[],
|
||||
quickSearch: string | null
|
||||
): Record<PropertyKey, unknown> {
|
||||
const where: Record<PropertyKey, unknown> = { ...this.accessWhere(access) };
|
||||
|
||||
for (const filter of filters) {
|
||||
const column = FIELD_MAP[filter.field];
|
||||
if (filter.operator === ">=" || filter.operator === "<") {
|
||||
where[column] = {
|
||||
...(typeof where[column] === "object" && where[column] !== null ? where[column] : {}),
|
||||
[filter.operator === ">=" ? Op.gte : Op.lt]: filter.value,
|
||||
};
|
||||
continue;
|
||||
}
|
||||
|
||||
where[column] = filter.value;
|
||||
}
|
||||
|
||||
if (quickSearch) {
|
||||
where[Op.and] = [{ [Op.or]: this.quickSearch(quickSearch) }];
|
||||
}
|
||||
|
||||
return where;
|
||||
}
|
||||
|
||||
async findById(id: string, access: AuditReadAccess): Promise<AuditDetail | null> {
|
||||
const row = await AuditEventModel.findOne({ where: { id, ...this.accessWhere(access) } });
|
||||
if (!row) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user