fix(validate) perbaikan validasi duplicate column

pull/2/head
ashar 2024-06-10 11:29:59 +07:00
parent 91dc7ad5b4
commit caa9ea14fc
16 changed files with 96 additions and 28 deletions

View File

@ -1,29 +1,40 @@
import { HttpStatus, UnprocessableEntityException } from '@nestjs/common'; import { HttpStatus, UnprocessableEntityException } from '@nestjs/common';
import { BaseDataService } from 'src/core/modules/data/service/base-data.service'; import { BaseDataService } from 'src/core/modules/data/service/base-data.service';
import { columnUniques } from 'src/core/strings/constants/interface.constants';
import { TABLE_NAME } from 'src/core/strings/constants/table.constants';
export class CheckDuplicateHelper { export class CheckDuplicateHelper {
constructor( constructor(
private dataService: BaseDataService<any>, private dataService: BaseDataService<any>,
private duplicateColumn: string[], private tableName: TABLE_NAME,
private duplicateColumn: columnUniques[],
private entity: any, private entity: any,
private entityId?: string, private entityId?: string,
) {} ) {}
async execute() { async execute() {
for (const column of this.duplicateColumn) { for (const columnCheck of this.duplicateColumn) {
const queryBuilder = this.dataService const queryBuilder = this.dataService
.getRepository() .getRepository()
.createQueryBuilder(); .createQueryBuilder(this.tableName);
queryBuilder.orWhere(
`replace(trim(lower(${column})), ' ',' ') = :query`, // process pengecekan column
queryBuilder.where(
`replace(trim(lower(${this.tableName}.${columnCheck.column})), ' ',' ') = :query`,
{ {
query: this.entity[column] query: this.entity[columnCheck.column]
?.toLowerCase() ?.toLowerCase()
.trim() .trim()
.replace(/ +(?= )/g, ''), .replace(/ +(?= )/g, ''),
}, },
); );
// jika ingin check specific data
if (columnCheck.query) {
queryBuilder.andWhere(columnCheck.query);
}
// jika update, akan membawa id. Maka dari itu, jangan validasi diri sendiri
if (this.entityId) { if (this.entityId) {
queryBuilder.andWhere(`id Not In ('${this.entityId}')`); queryBuilder.andWhere(`id Not In ('${this.entityId}')`);
} }
@ -32,7 +43,9 @@ export class CheckDuplicateHelper {
if (data_exists > 0) { if (data_exists > 0) {
throw new UnprocessableEntityException({ throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY, statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Entity with ${column} : ${this.entity[column]} already exist`, message: `Entity with ${columnCheck.column} : ${
this.entity[columnCheck.column]
} already exist`,
error: 'Unprocessable Entity', error: 'Unprocessable Entity',
}); });
} }

View File

@ -2,13 +2,16 @@ import { CheckDuplicateHelper } from 'src/core/helpers/query/check-duplicate.hel
import { BaseManager } from '../base.manager'; import { BaseManager } from '../base.manager';
import { RecordLog } from 'src/modules/configuration/log/domain/entities/log.event'; import { RecordLog } from 'src/modules/configuration/log/domain/entities/log.event';
import { OPERATION } from 'src/core/strings/constants/base.constants'; import { OPERATION } from 'src/core/strings/constants/base.constants';
import { validateRelations } from 'src/core/strings/constants/interface.constants'; import {
columnUniques,
validateRelations,
} from 'src/core/strings/constants/interface.constants';
export abstract class BaseCreateManager<Entity> extends BaseManager { export abstract class BaseCreateManager<Entity> extends BaseManager {
protected result: Entity; protected result: Entity;
protected duplicateColumn: string[]; protected duplicateColumn: string[];
abstract get entityTarget(): any; abstract get entityTarget(): any;
abstract get uniqueColumns(): string[]; abstract get uniqueColumns(): columnUniques[];
setData(entity: Entity): void { setData(entity: Entity): void {
this.data = entity; this.data = entity;
@ -31,6 +34,7 @@ export abstract class BaseCreateManager<Entity> extends BaseManager {
if (this.uniqueColumns.length) { if (this.uniqueColumns.length) {
await new CheckDuplicateHelper( await new CheckDuplicateHelper(
this.dataService, this.dataService,
this.tableName,
this.uniqueColumns, this.uniqueColumns,
this.data, this.data,
).execute(); ).execute();

View File

@ -1,13 +1,14 @@
import { CheckDuplicateHelper } from 'src/core/helpers/query/check-duplicate.helpers'; import { CheckDuplicateHelper } from 'src/core/helpers/query/check-duplicate.helpers';
import { BaseManager } from '../base.manager'; import { BaseManager } from '../base.manager';
import { ValidateRelationHelper } from 'src/core/helpers/validation/validate-relation.helper'; import { ValidateRelationHelper } from 'src/core/helpers/validation/validate-relation.helper';
import { columnUniques } from 'src/core/strings/constants/interface.constants';
export abstract class BaseUpdateManager<Entity> extends BaseManager { export abstract class BaseUpdateManager<Entity> extends BaseManager {
protected dataId: string; protected dataId: string;
protected result: Entity; protected result: Entity;
protected duplicateColumn: string[]; protected duplicateColumn: string[];
abstract get entityTarget(): any; abstract get entityTarget(): any;
abstract get uniqueColumns(): string[]; abstract get uniqueColumns(): columnUniques[];
setData(id: string, entity: Entity): void { setData(id: string, entity: Entity): void {
this.dataId = id; this.dataId = id;
@ -24,6 +25,7 @@ export abstract class BaseUpdateManager<Entity> extends BaseManager {
if (this.uniqueColumns.length) { if (this.uniqueColumns.length) {
await new CheckDuplicateHelper( await new CheckDuplicateHelper(
this.dataService, this.dataService,
this.tableName,
this.uniqueColumns, this.uniqueColumns,
this.data, this.data,
this.dataId, this.dataId,

View File

@ -11,6 +11,11 @@ export interface validateRelations {
message?: string; message?: string;
} }
export interface columnUniques {
column: string;
query?: Object;
}
export interface IEvent<Entity = any> { export interface IEvent<Entity = any> {
id: string; id: string;
old: null | Entity; old: null | Entity;

View File

@ -1,6 +1,6 @@
import { BaseBatchDeleteManager } from 'src/core/modules/domain/usecase/managers/base-batch-delete.manager'; import { BaseBatchDeleteManager } from 'src/core/modules/domain/usecase/managers/base-batch-delete.manager';
import { {{pascalCase name}}Entity } from '../../entities/{{dashCase name}}.entity'; import { {{pascalCase name}}Entity } from '../../entities/{{dashCase name}}.entity';
import { EventTopics } from 'src/core/strings/constants/interface.constants'; import { EventTopics, validateRelations } from 'src/core/strings/constants/interface.constants';
import { {{pascalCase name}}Model } from '../../../data/models/{{dashCase name}}.model'; import { {{pascalCase name}}Model } from '../../../data/models/{{dashCase name}}.model';
import { {{pascalCase name}}DeletedEvent } from '../../entities/event/{{dashCase name}}-deleted.event'; import { {{pascalCase name}}DeletedEvent } from '../../entities/event/{{dashCase name}}-deleted.event';
import { BatchResult } from 'src/core/response/domain/ok-response.interface'; import { BatchResult } from 'src/core/response/domain/ok-response.interface';
@ -20,6 +20,10 @@ export class BatchDelete{{pascalCase name}}Manager extends BaseBatchDeleteManage
return; return;
} }
get validateRelations(): validateRelations[] {
return [];
}
get entityTarget(): any { get entityTarget(): any {
return {{pascalCase name}}Model; return {{pascalCase name}}Model;
} }

View File

@ -1,5 +1,5 @@
import { Injectable } from "@nestjs/common"; import { Injectable } from "@nestjs/common";
import { EventTopics } from 'src/core/strings/constants/interface.constants'; import { EventTopics, columnUniques, validateRelations } from 'src/core/strings/constants/interface.constants';
import { {{pascalCase name}}Entity } from '../../entities/{{dashCase name}}.entity'; import { {{pascalCase name}}Entity } from '../../entities/{{dashCase name}}.entity';
import { {{pascalCase name}}Model } from '../../../data/models/{{dashCase name}}.model'; import { {{pascalCase name}}Model } from '../../../data/models/{{dashCase name}}.model';
import { BaseCreateManager } from 'src/core/modules/domain/usecase/managers/base-create.manager'; import { BaseCreateManager } from 'src/core/modules/domain/usecase/managers/base-create.manager';
@ -18,7 +18,11 @@ export class Create{{pascalCase name}}Manager extends BaseCreateManager<{{pascal
async generateConfig(): Promise<void> {} async generateConfig(): Promise<void> {}
get uniqueColumns(): string[] { get validateRelations(): validateRelations[] {
return [];
}
get uniqueColumns(): columnUniques[] {
return []; return [];
} }

View File

@ -1,7 +1,7 @@
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { BaseDeleteManager } from 'src/core/modules/domain/usecase/managers/base-delete.manager'; import { BaseDeleteManager } from 'src/core/modules/domain/usecase/managers/base-delete.manager';
import { {{pascalCase name}}Entity } from '../../entities/{{dashCase name}}.entity'; import { {{pascalCase name}}Entity } from '../../entities/{{dashCase name}}.entity';
import { EventTopics } from 'src/core/strings/constants/interface.constants'; import { EventTopics, validateRelations } from 'src/core/strings/constants/interface.constants';
import { {{pascalCase name}}Model } from '../../../data/models/{{dashCase name}}.model'; import { {{pascalCase name}}Model } from '../../../data/models/{{dashCase name}}.model';
import { {{pascalCase name}}DeletedEvent } from '../../entities/event/{{dashCase name}}-deleted.event'; import { {{pascalCase name}}DeletedEvent } from '../../entities/event/{{dashCase name}}-deleted.event';
@ -23,6 +23,10 @@ export class Delete{{pascalCase name}}Manager extends BaseDeleteManager<{{pascal
return; return;
} }
get validateRelations(): validateRelations[] {
return [];
}
get entityTarget(): any { get entityTarget(): any {
return {{pascalCase name}}Model; return {{pascalCase name}}Model;
} }

View File

@ -1,9 +1,9 @@
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { BaseUpdateManager } from 'src/core/modules/domain/usecase/managers/base-update.manager'; import { BaseUpdateManager } from 'src/core/modules/domain/usecase/managers/base-update.manager';
import { {{pascalCase name}}Entity } from '../../entities/{{dashCase name}}.entity'; import { {{pascalCase name}}Entity } from '../../entities/{{dashCase name}}.entity';
import { EventTopics } from 'src/core/strings/constants/interface.constants';
import { {{pascalCase name}}Model } from '../../../data/models/{{dashCase name}}.model'; import { {{pascalCase name}}Model } from '../../../data/models/{{dashCase name}}.model';
import { {{pascalCase name}}UpdatedEvent } from '../../entities/event/{{dashCase name}}-updated.event'; import { {{pascalCase name}}UpdatedEvent } from '../../entities/event/{{dashCase name}}-updated.event';
import { EventTopics, columnUniques, validateRelations } from 'src/core/strings/constants/interface.constants';
@Injectable() @Injectable()
export class Update{{pascalCase name}}Manager extends BaseUpdateManager<{{pascalCase name}}Entity> { export class Update{{pascalCase name}}Manager extends BaseUpdateManager<{{pascalCase name}}Entity> {
@ -19,8 +19,12 @@ export class Update{{pascalCase name}}Manager extends BaseUpdateManager<{{pascal
return; return;
} }
get uniqueColumns(): string[] { get validateRelations(): validateRelations[] {
return ['name']; return [];
}
get uniqueColumns(): columnUniques[] {
return [];
} }
get entityTarget(): any { get entityTarget(): any {

View File

@ -1,7 +1,7 @@
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { BaseUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-update-status.manager'; import { BaseUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-update-status.manager';
import { {{pascalCase name}}Entity } from '../../entities/{{dashCase name}}.entity'; import { {{pascalCase name}}Entity } from '../../entities/{{dashCase name}}.entity';
import { EventTopics } from 'src/core/strings/constants/interface.constants'; import { EventTopics, validateRelations } from 'src/core/strings/constants/interface.constants';
import { {{pascalCase name}}Model } from '../../../data/models/{{dashCase name}}.model'; import { {{pascalCase name}}Model } from '../../../data/models/{{dashCase name}}.model';
import { {{pascalCase name}}ChangeStatusEvent } from '../../entities/event/{{dashCase name}}-change-status.event'; import { {{pascalCase name}}ChangeStatusEvent } from '../../entities/event/{{dashCase name}}-change-status.event';
@ -23,6 +23,10 @@ export class Active{{pascalCase name}}Manager extends BaseUpdateStatusManager<{{
return; return;
} }
get validateRelations(): validateRelations[] {
return [];
}
get entityTarget(): any { get entityTarget(): any {
return {{pascalCase name}}Model; return {{pascalCase name}}Model;
} }

View File

@ -1,6 +1,6 @@
import { BaseBatchUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-batch-update-status.manager'; import { BaseBatchUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-batch-update-status.manager';
import { {{pascalCase name}}Entity } from '../../entities/{{dashCase name}}.entity'; import { {{pascalCase name}}Entity } from '../../entities/{{dashCase name}}.entity';
import { EventTopics } from 'src/core/strings/constants/interface.constants'; import { EventTopics, validateRelations } from 'src/core/strings/constants/interface.constants';
import { {{pascalCase name}}Model } from '../../../data/models/{{dashCase name}}.model'; import { {{pascalCase name}}Model } from '../../../data/models/{{dashCase name}}.model';
import { {{pascalCase name}}ChangeStatusEvent } from '../../entities/event/{{dashCase name}}-change-status.event'; import { {{pascalCase name}}ChangeStatusEvent } from '../../entities/event/{{dashCase name}}-change-status.event';
import { BatchResult } from 'src/core/response/domain/ok-response.interface'; import { BatchResult } from 'src/core/response/domain/ok-response.interface';
@ -20,6 +20,10 @@ export class BatchActive{{pascalCase name}}Manager extends BaseBatchUpdateStatus
return; return;
} }
get validateRelations(): validateRelations[] {
return [];
}
get entityTarget(): any { get entityTarget(): any {
return {{pascalCase name}}Model; return {{pascalCase name}}Model;
} }

View File

@ -1,6 +1,6 @@
import { BaseBatchUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-batch-update-status.manager'; import { BaseBatchUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-batch-update-status.manager';
import { {{pascalCase name}}Entity } from '../../entities/{{dashCase name}}.entity'; import { {{pascalCase name}}Entity } from '../../entities/{{dashCase name}}.entity';
import { EventTopics } from 'src/core/strings/constants/interface.constants'; import { EventTopics, validateRelations } from 'src/core/strings/constants/interface.constants';
import { {{pascalCase name}}Model } from '../../../data/models/{{dashCase name}}.model'; import { {{pascalCase name}}Model } from '../../../data/models/{{dashCase name}}.model';
import { {{pascalCase name}}ChangeStatusEvent } from '../../entities/event/{{dashCase name}}-change-status.event'; import { {{pascalCase name}}ChangeStatusEvent } from '../../entities/event/{{dashCase name}}-change-status.event';
import { BatchResult } from 'src/core/response/domain/ok-response.interface'; import { BatchResult } from 'src/core/response/domain/ok-response.interface';
@ -20,6 +20,10 @@ export class BatchConfirm{{pascalCase name}}Manager extends BaseBatchUpdateStatu
return; return;
} }
get validateRelations(): validateRelations[] {
return [];
}
get entityTarget(): any { get entityTarget(): any {
return {{pascalCase name}}Model; return {{pascalCase name}}Model;
} }

View File

@ -1,6 +1,6 @@
import { BaseBatchUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-batch-update-status.manager'; import { BaseBatchUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-batch-update-status.manager';
import { {{pascalCase name}}Entity } from '../../entities/{{dashCase name}}.entity'; import { {{pascalCase name}}Entity } from '../../entities/{{dashCase name}}.entity';
import { EventTopics } from 'src/core/strings/constants/interface.constants'; import { EventTopics, validateRelations } from 'src/core/strings/constants/interface.constants';
import { {{pascalCase name}}Model } from '../../../data/models/{{dashCase name}}.model'; import { {{pascalCase name}}Model } from '../../../data/models/{{dashCase name}}.model';
import { {{pascalCase name}}ChangeStatusEvent } from '../../entities/event/{{dashCase name}}-change-status.event'; import { {{pascalCase name}}ChangeStatusEvent } from '../../entities/event/{{dashCase name}}-change-status.event';
import { BatchResult } from 'src/core/response/domain/ok-response.interface'; import { BatchResult } from 'src/core/response/domain/ok-response.interface';
@ -20,6 +20,10 @@ export class BatchInactive{{pascalCase name}}Manager extends BaseBatchUpdateStat
return; return;
} }
get validateRelations(): validateRelations[] {
return [];
}
get entityTarget(): any { get entityTarget(): any {
return {{pascalCase name}}Model; return {{pascalCase name}}Model;
} }

View File

@ -1,7 +1,7 @@
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { BaseUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-update-status.manager'; import { BaseUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-update-status.manager';
import { {{pascalCase name}}Entity } from '../../entities/{{dashCase name}}.entity'; import { {{pascalCase name}}Entity } from '../../entities/{{dashCase name}}.entity';
import { EventTopics } from 'src/core/strings/constants/interface.constants'; import { EventTopics, validateRelations } from 'src/core/strings/constants/interface.constants';
import { {{pascalCase name}}Model } from '../../../data/models/{{dashCase name}}.model'; import { {{pascalCase name}}Model } from '../../../data/models/{{dashCase name}}.model';
import { {{pascalCase name}}ChangeStatusEvent } from '../../entities/event/{{dashCase name}}-change-status.event'; import { {{pascalCase name}}ChangeStatusEvent } from '../../entities/event/{{dashCase name}}-change-status.event';
@ -23,6 +23,10 @@ export class Confirm{{pascalCase name}}Manager extends BaseUpdateStatusManager<{
return; return;
} }
get validateRelations(): validateRelations[] {
return [];
}
get entityTarget(): any { get entityTarget(): any {
return {{pascalCase name}}Model; return {{pascalCase name}}Model;
} }

View File

@ -1,7 +1,7 @@
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { BaseUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-update-status.manager'; import { BaseUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-update-status.manager';
import { {{pascalCase name}}Entity } from '../../entities/{{dashCase name}}.entity'; import { {{pascalCase name}}Entity } from '../../entities/{{dashCase name}}.entity';
import { EventTopics } from 'src/core/strings/constants/interface.constants'; import { EventTopics, validateRelations } from 'src/core/strings/constants/interface.constants';
import { {{pascalCase name}}Model } from '../../../data/models/{{dashCase name}}.model'; import { {{pascalCase name}}Model } from '../../../data/models/{{dashCase name}}.model';
import { {{pascalCase name}}ChangeStatusEvent } from '../../entities/event/{{dashCase name}}-change-status.event'; import { {{pascalCase name}}ChangeStatusEvent } from '../../entities/event/{{dashCase name}}-change-status.event';
@ -23,6 +23,10 @@ export class Inactive{{pascalCase name}}Manager extends BaseUpdateStatusManager<
return; return;
} }
get validateRelations(): validateRelations[] {
return [];
}
get entityTarget(): any { get entityTarget(): any {
return {{pascalCase name}}Model; return {{pascalCase name}}Model;
} }

View File

@ -2,7 +2,10 @@ import { BaseCreateManager } from 'src/core/modules/domain/usecase/managers/base
import { UserPrivilegeEntity } from '../../../entities/user-privilege.entity'; import { UserPrivilegeEntity } from '../../../entities/user-privilege.entity';
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { UserPrivilegeModel } from '../../../../data/models/user-privilege.model'; import { UserPrivilegeModel } from '../../../../data/models/user-privilege.model';
import { EventTopics } from 'src/core/strings/constants/interface.constants'; import {
EventTopics,
columnUniques,
} from 'src/core/strings/constants/interface.constants';
import { UserPrivilegeCreatedEvent } from '../../../entities/event/user-privilege-created.event'; import { UserPrivilegeCreatedEvent } from '../../../entities/event/user-privilege-created.event';
import { UserPrivilegeConfigurationHelper } from '../../user-privilege-configuration/helpers/generate-user-privilege-configuration.helper'; import { UserPrivilegeConfigurationHelper } from '../../user-privilege-configuration/helpers/generate-user-privilege-configuration.helper';
@ -23,8 +26,8 @@ export class CreateUserPrivilegeManager extends BaseCreateManager<UserPrivilegeE
async generateConfig(): Promise<void> {} async generateConfig(): Promise<void> {}
get uniqueColumns(): string[] { get uniqueColumns(): columnUniques[] {
return ['name']; return [{ column: 'name' }];
} }
get eventTopics(): EventTopics[] { get eventTopics(): EventTopics[] {

View File

@ -3,6 +3,7 @@ import { BaseUpdateManager } from 'src/core/modules/domain/usecase/managers/base
import { UserPrivilegeEntity } from '../../../entities/user-privilege.entity'; import { UserPrivilegeEntity } from '../../../entities/user-privilege.entity';
import { import {
EventTopics, EventTopics,
columnUniques,
validateRelations, validateRelations,
} from 'src/core/strings/constants/interface.constants'; } from 'src/core/strings/constants/interface.constants';
import { UserPrivilegeModel } from '../../../../data/models/user-privilege.model'; import { UserPrivilegeModel } from '../../../../data/models/user-privilege.model';
@ -26,8 +27,8 @@ export class UpdateUserPrivilegeManager extends BaseUpdateManager<UserPrivilegeE
return []; return [];
} }
get uniqueColumns(): string[] { get uniqueColumns(): columnUniques[] {
return ['name']; return [{ column: 'name' }];
} }
get entityTarget(): any { get entityTarget(): any {