feat(SPG-7) Data Validation

pull/2/head
ashar 2024-06-06 14:59:51 +07:00
parent 5802dc3c92
commit c5c5762823
20 changed files with 183 additions and 11 deletions

View File

@ -0,0 +1,43 @@
import { Injectable, UnprocessableEntityException } from '@nestjs/common';
import { BaseDataService } from 'src/core/modules/data/service/base-data.service';
import { validateRelations } from 'src/core/strings/constants/interface.constants';
@Injectable()
export class ValidateRelationHelper<Entity> {
constructor(
private dataId: string,
private dataService: BaseDataService<Entity>,
private relations: validateRelations[],
private tableName: string,
) {}
async execute() {
const repository = this.dataService.getRepository();
const queryBuilder = repository.createQueryBuilder(this.tableName);
// load relation
for (const relation of this.relations) {
queryBuilder.loadRelationCountAndMap(
`${this.tableName}.total_${relation.relation}`,
`${this.tableName}.${relation.relation}`,
`total_${relation.relation}`,
);
}
// filtering data only with specific data
queryBuilder.where(`${this.tableName}.id in ('${this.dataId}')`);
// get data
const data = await queryBuilder.getOne();
// process validasi
for (const relation of this.relations) {
const message =
relation.message ??
`Failed! this data already connected to ${relation.relation}`;
if (data[`total_${relation.relation}`])
throw new UnprocessableEntityException(message);
}
}
}

View File

@ -2,7 +2,10 @@ import { Inject, Injectable, Logger } from '@nestjs/common';
import { EventBus } from '@nestjs/cqrs'; import { EventBus } from '@nestjs/cqrs';
import { UserProvider, UsersSession } from 'src/core/sessions'; import { UserProvider, UsersSession } from 'src/core/sessions';
import { BLANK_USER } from 'src/core/strings/constants/base.constants'; import { BLANK_USER } from 'src/core/strings/constants/base.constants';
import { EventTopics } from 'src/core/strings/constants/interface.constants'; import {
EventTopics,
validateRelations,
} from 'src/core/strings/constants/interface.constants';
import { TABLE_NAME } from 'src/core/strings/constants/table.constants'; import { TABLE_NAME } from 'src/core/strings/constants/table.constants';
import { QueryRunner } from 'typeorm'; import { QueryRunner } from 'typeorm';
@ -17,6 +20,7 @@ export abstract class BaseManager {
protected userProvider: UserProvider; protected userProvider: UserProvider;
@Inject() @Inject()
protected eventBus: EventBus; protected eventBus: EventBus;
abstract get validateRelations(): validateRelations[];
private readonly baseLog = new Logger(BaseManager.name); private readonly baseLog = new Logger(BaseManager.name);

View File

@ -1,6 +1,7 @@
import { BatchResult } from 'src/core/response/domain/ok-response.interface'; import { BatchResult } from 'src/core/response/domain/ok-response.interface';
import { BaseManager } from '../base.manager'; import { BaseManager } from '../base.manager';
import { HttpStatus, NotFoundException } from '@nestjs/common'; import { HttpStatus, NotFoundException } from '@nestjs/common';
import { ValidateRelationHelper } from 'src/core/helpers/validation/validate-relation.helper';
export abstract class BaseBatchDeleteManager<Entity> extends BaseManager { export abstract class BaseBatchDeleteManager<Entity> extends BaseManager {
protected dataIds: string[]; protected dataIds: string[];
@ -41,6 +42,13 @@ export abstract class BaseBatchDeleteManager<Entity> extends BaseManager {
} }
await this.validateData(entity); await this.validateData(entity);
await new ValidateRelationHelper(
id,
this.dataService,
this.validateRelations,
this.tableName,
).execute();
await this.dataService.deleteById( await this.dataService.deleteById(
this.queryRunner, this.queryRunner,
this.entityTarget, this.entityTarget,

View File

@ -2,6 +2,7 @@ import { BatchResult } from 'src/core/response/domain/ok-response.interface';
import { BaseManager } from '../base.manager'; import { BaseManager } from '../base.manager';
import { HttpStatus, NotFoundException } from '@nestjs/common'; import { HttpStatus, NotFoundException } from '@nestjs/common';
import { STATUS } from 'src/core/strings/constants/base.constants'; import { STATUS } from 'src/core/strings/constants/base.constants';
import { ValidateRelationHelper } from 'src/core/helpers/validation/validate-relation.helper';
export abstract class BaseBatchUpdateStatusManager<Entity> extends BaseManager { export abstract class BaseBatchUpdateStatusManager<Entity> extends BaseManager {
protected dataIds: string[]; protected dataIds: string[];
@ -44,6 +45,13 @@ export abstract class BaseBatchUpdateStatusManager<Entity> extends BaseManager {
} }
await this.validateData(entity); await this.validateData(entity);
await new ValidateRelationHelper(
id,
this.dataService,
this.validateRelations,
this.tableName,
).execute();
await this.dataService.update( await this.dataService.update(
this.queryRunner, this.queryRunner,
this.entityTarget, this.entityTarget,

View File

@ -2,6 +2,7 @@ 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';
export abstract class BaseCreateManager<Entity> extends BaseManager { export abstract class BaseCreateManager<Entity> extends BaseManager {
protected result: Entity; protected result: Entity;
@ -13,6 +14,10 @@ export abstract class BaseCreateManager<Entity> extends BaseManager {
this.data = entity; this.data = entity;
} }
get validateRelations(): validateRelations[] {
return [];
}
async prepareData(): Promise<void> { async prepareData(): Promise<void> {
Object.assign(this.data, { Object.assign(this.data, {
creator_id: this.user.id, creator_id: this.user.id,

View File

@ -1,3 +1,4 @@
import { validateRelations } from 'src/core/strings/constants/interface.constants';
import { BaseManager } from '../base.manager'; import { BaseManager } from '../base.manager';
export abstract class BaseCustomManager<Entity> extends BaseManager { export abstract class BaseCustomManager<Entity> extends BaseManager {
@ -8,6 +9,10 @@ export abstract class BaseCustomManager<Entity> extends BaseManager {
this.data = entity; this.data = entity;
} }
get validateRelations(): validateRelations[] {
return [];
}
async prepareData(): Promise<void> { async prepareData(): Promise<void> {
if (this.data) if (this.data)
Object.assign(this.data, { Object.assign(this.data, {

View File

@ -1,5 +1,6 @@
import { HttpStatus, UnprocessableEntityException } from '@nestjs/common'; import { HttpStatus, UnprocessableEntityException } from '@nestjs/common';
import { BaseManager } from '../base.manager'; import { BaseManager } from '../base.manager';
import { ValidateRelationHelper } from 'src/core/helpers/validation/validate-relation.helper';
export abstract class BaseDeleteManager<Entity> extends BaseManager { export abstract class BaseDeleteManager<Entity> extends BaseManager {
protected dataId: string; protected dataId: string;
@ -28,6 +29,13 @@ export abstract class BaseDeleteManager<Entity> extends BaseManager {
} }
async process(): Promise<void> { async process(): Promise<void> {
await new ValidateRelationHelper(
this.dataId,
this.dataService,
this.validateRelations,
this.tableName,
).execute();
await this.dataService.deleteById( await this.dataService.deleteById(
this.queryRunner, this.queryRunner,
this.entityTarget, this.entityTarget,

View File

@ -1,3 +1,4 @@
import { ValidateRelationHelper } from 'src/core/helpers/validation/validate-relation.helper';
import { BaseManager } from '../base.manager'; import { BaseManager } from '../base.manager';
import { STATUS } from 'src/core/strings/constants/base.constants'; import { STATUS } from 'src/core/strings/constants/base.constants';
import { UserPrivilegeModel } from 'src/modules/user-related/user-privilege/data/models/user-privilege.model'; import { UserPrivilegeModel } from 'src/modules/user-related/user-privilege/data/models/user-privilege.model';
@ -27,6 +28,13 @@ export abstract class BaseUpdateStatusManager<Entity> extends BaseManager {
} }
async process(): Promise<void> { async process(): Promise<void> {
await new ValidateRelationHelper(
this.dataId,
this.dataService,
this.validateRelations,
this.tableName,
).execute();
this.result = await this.dataService.update( this.result = await this.dataService.update(
this.queryRunner, this.queryRunner,
this.entityTarget, this.entityTarget,

View File

@ -1,5 +1,6 @@
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';
export abstract class BaseUpdateManager<Entity> extends BaseManager { export abstract class BaseUpdateManager<Entity> extends BaseManager {
protected dataId: string; protected dataId: string;
@ -31,6 +32,13 @@ export abstract class BaseUpdateManager<Entity> extends BaseManager {
} }
async process(): Promise<void> { async process(): Promise<void> {
await new ValidateRelationHelper(
this.dataId,
this.dataService,
this.validateRelations,
this.tableName,
).execute();
this.result = await this.dataService.update( this.result = await this.dataService.update(
this.queryRunner, this.queryRunner,
this.entityTarget, this.entityTarget,

View File

@ -6,6 +6,11 @@ export interface EventTopics {
data?: any; data?: any;
} }
export interface validateRelations {
relation: string;
message?: string;
}
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,9 @@
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { UserPrivilegeConfigurationEntity } from '../../../entities/user-privilege-configuration.entity'; import { UserPrivilegeConfigurationEntity } from '../../../entities/user-privilege-configuration.entity';
import { EventTopics } from 'src/core/strings/constants/interface.constants'; import {
EventTopics,
validateRelations,
} from 'src/core/strings/constants/interface.constants';
import { BaseCustomManager } from 'src/core/modules/domain/usecase/managers/base-custom.manager'; import { BaseCustomManager } from 'src/core/modules/domain/usecase/managers/base-custom.manager';
import { UserPrivilegeConfigurationModel } from 'src/modules/user-related/user-privilege/data/models/user-privilege-configuration.model'; import { UserPrivilegeConfigurationModel } from 'src/modules/user-related/user-privilege/data/models/user-privilege-configuration.model';
@ -28,6 +31,10 @@ export class UpdateUserPrivilegeConfigurationManager extends BaseCustomManager<U
return; return;
} }
get validateRelations(): validateRelations[] {
return [];
}
getResult() { getResult() {
return this.result; return this.result;
} }

View File

@ -1,7 +1,10 @@
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 { UserPrivilegeEntity } from '../../../entities/user-privilege.entity'; import { UserPrivilegeEntity } from '../../../entities/user-privilege.entity';
import { EventTopics } from 'src/core/strings/constants/interface.constants'; import {
EventTopics,
validateRelations,
} from 'src/core/strings/constants/interface.constants';
import { UserPrivilegeModel } from '../../../../data/models/user-privilege.model'; import { UserPrivilegeModel } from '../../../../data/models/user-privilege.model';
import { UserPrivilegeChangeStatusEvent } from '../../../entities/event/user-privilege-change-status.event'; import { UserPrivilegeChangeStatusEvent } from '../../../entities/event/user-privilege-change-status.event';
@ -23,6 +26,10 @@ export class ActiveUserPrivilegeManager extends BaseUpdateStatusManager<UserPriv
return; return;
} }
get validateRelations(): validateRelations[] {
return [];
}
get entityTarget(): any { get entityTarget(): any {
return UserPrivilegeModel; return UserPrivilegeModel;
} }

View File

@ -1,6 +1,9 @@
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 { UserPrivilegeEntity } from '../../../entities/user-privilege.entity'; import { UserPrivilegeEntity } from '../../../entities/user-privilege.entity';
import { EventTopics } from 'src/core/strings/constants/interface.constants'; import {
EventTopics,
validateRelations,
} from 'src/core/strings/constants/interface.constants';
import { UserPrivilegeModel } from '../../../../data/models/user-privilege.model'; import { UserPrivilegeModel } from '../../../../data/models/user-privilege.model';
import { UserPrivilegeChangeStatusEvent } from '../../../entities/event/user-privilege-change-status.event'; import { UserPrivilegeChangeStatusEvent } from '../../../entities/event/user-privilege-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 +23,10 @@ export class BatchActiveUserPrivilegeManager extends BaseBatchUpdateStatusManage
return; return;
} }
get validateRelations(): validateRelations[] {
return [];
}
get entityTarget(): any { get entityTarget(): any {
return UserPrivilegeModel; return UserPrivilegeModel;
} }

View File

@ -1,6 +1,9 @@
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 { UserPrivilegeEntity } from '../../../entities/user-privilege.entity'; import { UserPrivilegeEntity } from '../../../entities/user-privilege.entity';
import { EventTopics } from 'src/core/strings/constants/interface.constants'; import {
EventTopics,
validateRelations,
} from 'src/core/strings/constants/interface.constants';
import { UserPrivilegeModel } from '../../../../data/models/user-privilege.model'; import { UserPrivilegeModel } from '../../../../data/models/user-privilege.model';
import { UserPrivilegeChangeStatusEvent } from '../../../entities/event/user-privilege-change-status.event'; import { UserPrivilegeChangeStatusEvent } from '../../../entities/event/user-privilege-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 +23,10 @@ export class BatchConfirmUserPrivilegeManager extends BaseBatchUpdateStatusManag
return; return;
} }
get validateRelations(): validateRelations[] {
return [];
}
get entityTarget(): any { get entityTarget(): any {
return UserPrivilegeModel; return UserPrivilegeModel;
} }

View File

@ -1,6 +1,9 @@
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 { UserPrivilegeEntity } from '../../../entities/user-privilege.entity'; import { UserPrivilegeEntity } from '../../../entities/user-privilege.entity';
import { EventTopics } from 'src/core/strings/constants/interface.constants'; import {
EventTopics,
validateRelations,
} from 'src/core/strings/constants/interface.constants';
import { UserPrivilegeModel } from '../../../../data/models/user-privilege.model'; import { UserPrivilegeModel } from '../../../../data/models/user-privilege.model';
import { UserPrivilegeDeletedEvent } from '../../../entities/event/user-privilege-deleted.event'; import { UserPrivilegeDeletedEvent } from '../../../entities/event/user-privilege-deleted.event';
import { BatchResult } from 'src/core/response/domain/ok-response.interface'; import { BatchResult } from 'src/core/response/domain/ok-response.interface';
@ -20,6 +23,10 @@ export class BatchDeleteUserPrivilegeManager extends BaseBatchDeleteManager<User
return; return;
} }
get validateRelations(): validateRelations[] {
return [];
}
get entityTarget(): any { get entityTarget(): any {
return UserPrivilegeModel; return UserPrivilegeModel;
} }

View File

@ -1,6 +1,9 @@
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 { UserPrivilegeEntity } from '../../../entities/user-privilege.entity'; import { UserPrivilegeEntity } from '../../../entities/user-privilege.entity';
import { EventTopics } from 'src/core/strings/constants/interface.constants'; import {
EventTopics,
validateRelations,
} from 'src/core/strings/constants/interface.constants';
import { UserPrivilegeModel } from '../../../../data/models/user-privilege.model'; import { UserPrivilegeModel } from '../../../../data/models/user-privilege.model';
import { UserPrivilegeChangeStatusEvent } from '../../../entities/event/user-privilege-change-status.event'; import { UserPrivilegeChangeStatusEvent } from '../../../entities/event/user-privilege-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 +23,10 @@ export class BatchInactiveUserPrivilegeManager extends BaseBatchUpdateStatusMana
return; return;
} }
get validateRelations(): validateRelations[] {
return [];
}
get entityTarget(): any { get entityTarget(): any {
return UserPrivilegeModel; return UserPrivilegeModel;
} }

View File

@ -1,7 +1,10 @@
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 { UserPrivilegeEntity } from '../../../entities/user-privilege.entity'; import { UserPrivilegeEntity } from '../../../entities/user-privilege.entity';
import { EventTopics } from 'src/core/strings/constants/interface.constants'; import {
EventTopics,
validateRelations,
} from 'src/core/strings/constants/interface.constants';
import { UserPrivilegeModel } from '../../../../data/models/user-privilege.model'; import { UserPrivilegeModel } from '../../../../data/models/user-privilege.model';
import { UserPrivilegeChangeStatusEvent } from '../../../entities/event/user-privilege-change-status.event'; import { UserPrivilegeChangeStatusEvent } from '../../../entities/event/user-privilege-change-status.event';
@ -23,6 +26,10 @@ export class ConfirmUserPrivilegeManager extends BaseUpdateStatusManager<UserPri
return; return;
} }
get validateRelations(): validateRelations[] {
return [];
}
get entityTarget(): any { get entityTarget(): any {
return UserPrivilegeModel; return UserPrivilegeModel;
} }

View File

@ -1,7 +1,10 @@
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 { UserPrivilegeEntity } from '../../../entities/user-privilege.entity'; import { UserPrivilegeEntity } from '../../../entities/user-privilege.entity';
import { EventTopics } from 'src/core/strings/constants/interface.constants'; import {
EventTopics,
validateRelations,
} from 'src/core/strings/constants/interface.constants';
import { UserPrivilegeModel } from '../../../../data/models/user-privilege.model'; import { UserPrivilegeModel } from '../../../../data/models/user-privilege.model';
import { UserPrivilegeDeletedEvent } from '../../../entities/event/user-privilege-deleted.event'; import { UserPrivilegeDeletedEvent } from '../../../entities/event/user-privilege-deleted.event';
@ -23,6 +26,10 @@ export class DeleteUserPrivilegeManager extends BaseDeleteManager<UserPrivilegeE
return; return;
} }
get validateRelations(): validateRelations[] {
return [];
}
get entityTarget(): any { get entityTarget(): any {
return UserPrivilegeModel; return UserPrivilegeModel;
} }

View File

@ -1,7 +1,10 @@
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 { UserPrivilegeEntity } from '../../../entities/user-privilege.entity'; import { UserPrivilegeEntity } from '../../../entities/user-privilege.entity';
import { EventTopics } from 'src/core/strings/constants/interface.constants'; import {
EventTopics,
validateRelations,
} from 'src/core/strings/constants/interface.constants';
import { UserPrivilegeModel } from '../../../../data/models/user-privilege.model'; import { UserPrivilegeModel } from '../../../../data/models/user-privilege.model';
import { UserPrivilegeChangeStatusEvent } from '../../../entities/event/user-privilege-change-status.event'; import { UserPrivilegeChangeStatusEvent } from '../../../entities/event/user-privilege-change-status.event';
@ -23,6 +26,10 @@ export class InactiveUserPrivilegeManager extends BaseUpdateStatusManager<UserPr
return; return;
} }
get validateRelations(): validateRelations[] {
return [];
}
get entityTarget(): any { get entityTarget(): any {
return UserPrivilegeModel; return UserPrivilegeModel;
} }

View File

@ -1,7 +1,10 @@
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 { UserPrivilegeEntity } from '../../../entities/user-privilege.entity'; import { UserPrivilegeEntity } from '../../../entities/user-privilege.entity';
import { EventTopics } from 'src/core/strings/constants/interface.constants'; import {
EventTopics,
validateRelations,
} from 'src/core/strings/constants/interface.constants';
import { UserPrivilegeModel } from '../../../../data/models/user-privilege.model'; import { UserPrivilegeModel } from '../../../../data/models/user-privilege.model';
import { UserPrivilegeUpdatedEvent } from '../../../entities/event/user-privilege-updated.event'; import { UserPrivilegeUpdatedEvent } from '../../../entities/event/user-privilege-updated.event';
@ -19,6 +22,10 @@ export class UpdateUserPrivilegeManager extends BaseUpdateManager<UserPrivilegeE
return; return;
} }
get validateRelations(): validateRelations[] {
return [];
}
get uniqueColumns(): string[] { get uniqueColumns(): string[] {
return ['name']; return ['name'];
} }