Complete question transition validation
This commit is contained in:
@@ -22,7 +22,24 @@
|
|||||||
"questionTransition": {
|
"questionTransition": {
|
||||||
"sameQuestion": "fromQuestion and toQuestion are the same",
|
"sameQuestion": "fromQuestion and toQuestion are the same",
|
||||||
"fromQuestionNotBelongToTest": "fromQuestion doesnt belong to the test.",
|
"fromQuestionNotBelongToTest": "fromQuestion doesnt belong to the test.",
|
||||||
"toQuestionNotBelongToTest": "toQuestion doesnt belong to the test."
|
"toQuestionNotBelongToTest": "toQuestion doesnt belong to the test.",
|
||||||
|
"startMustNotHaveFromQuestion": "Start must not have fromQuestion.",
|
||||||
|
"startMustHaveToQuestion": "Start must have toQuestion.",
|
||||||
|
"startMustNotHaveCondition": "Start must not have condition.",
|
||||||
|
"endMustHaveFromQuestion": "End must have fromQuestion.",
|
||||||
|
"endMustNotHaveToQuestion": "End must not have toQuestion.",
|
||||||
|
"endMustNotHaveCondition": "End must not have condition.",
|
||||||
|
"invalidTransition": "Invalid Transition!",
|
||||||
|
"defaultMustNotHaveCondition": "Default must not have condition.",
|
||||||
|
"fromQuestionMustBeMultiChoice": "fromQuestion must be multi choice.",
|
||||||
|
"invalidChoiceCondition": "Invalid choice condition!",
|
||||||
|
"choiceNotBelongToQuestion": "Choice does not belong to the question.",
|
||||||
|
"fromQuestionMustBeNumeric": "fromQuestion must be numeric.",
|
||||||
|
"invalidNumberRange": "Invalid number range!",
|
||||||
|
"startAlreadyExists": "Start already exists.",
|
||||||
|
"endAlreadyExists": "End already exists.",
|
||||||
|
"defaultAlreadyExists": "Default already exists.",
|
||||||
|
"duplicateTransition": "Duplicate Transition!"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"messages": {
|
"messages": {
|
||||||
|
|||||||
@@ -22,7 +22,24 @@
|
|||||||
"questionTransition": {
|
"questionTransition": {
|
||||||
"sameQuestion": "سوال مبدا و مقصد یکی است.",
|
"sameQuestion": "سوال مبدا و مقصد یکی است.",
|
||||||
"fromQuestionNotBelongToTest": "سوال مبدا متعلق به تست نیست.",
|
"fromQuestionNotBelongToTest": "سوال مبدا متعلق به تست نیست.",
|
||||||
"toQuestionNotBelongToTest": "سوال مقصد متعلق به تست نیست."
|
"toQuestionNotBelongToTest": "سوال مقصد متعلق به تست نیست.",
|
||||||
|
"startMustNotHaveFromQuestion": "حالت شروع نباید سوال مبدا داشته باشد.",
|
||||||
|
"startMustHaveToQuestion": "حالت شروع باید سوال مقصد داشته باشد.",
|
||||||
|
"startMustNotHaveCondition": "حالت شروع نباید شرط داشته باشد.",
|
||||||
|
"endMustHaveFromQuestion": "حالت پایان باید سوال مقصد داشته باشد.",
|
||||||
|
"endMustNotHaveToQuestion": "حالت پایان نباید سوال مبدا داشته باشد.",
|
||||||
|
"endMustNotHaveCondition": "حالت پایان نباید شرط داشته باشد.",
|
||||||
|
"invalidTransition": "مسیر اشتباه است!",
|
||||||
|
"defaultMustNotHaveCondition": "حالت پیشفرض نباید شرط داشته باشد.",
|
||||||
|
"fromQuestionMustBeMultiChoice": "سوال مبدا باید چند گزینه ای باشد.",
|
||||||
|
"invalidChoiceCondition": "شرط گزینه اشتباه است!",
|
||||||
|
"choiceNotBelongToQuestion": "گزینه متعلق به سوال نیست.",
|
||||||
|
"fromQuestionMustBeNumeric": "سوال مبدا باید از نوع عددی باشد.",
|
||||||
|
"invalidNumberRange": "بازه عددی اشتباه است!",
|
||||||
|
"startAlreadyExists": "حالت شروع وجود دارد.",
|
||||||
|
"endAlreadyExists": "حالت پایان وجود دارد.",
|
||||||
|
"defaultAlreadyExists": "حالت پیشفرض وجود دارد.",
|
||||||
|
"duplicateTransition": "مسیر تکراری است!"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"messages": {
|
"messages": {
|
||||||
|
|||||||
+171
@@ -0,0 +1,171 @@
|
|||||||
|
import { AppException } from '@/common/exceptions/app.exception';
|
||||||
|
import { QuestionTransition } from '@/modules/questions/entities/question-transition.entity';
|
||||||
|
import { QuestionTransitionType } from '@/modules/questions/enums/question-transition-type.enum';
|
||||||
|
import { NumericCondition } from '@/modules/questions/interfaces/numeric-condition.interface';
|
||||||
|
import { SingleChoiceCondition } from '@/modules/questions/interfaces/single-choice-condition.interface';
|
||||||
|
import { TransitionValidateOptions } from '@/modules/questions/interfaces/transition-validate-options.interface';
|
||||||
|
import { HttpStatus, Injectable } from '@nestjs/common';
|
||||||
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
|
import type { Repository } from 'typeorm';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class CheckTransitionDBProvider {
|
||||||
|
constructor(
|
||||||
|
/**
|
||||||
|
* Inject Transitions Repository
|
||||||
|
*/
|
||||||
|
@InjectRepository(QuestionTransition)
|
||||||
|
private readonly transitionsRepository: Repository<QuestionTransition>,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public async validate(
|
||||||
|
options: TransitionValidateOptions,
|
||||||
|
transitionId?: number,
|
||||||
|
) {
|
||||||
|
await this.validateSingleStart(options, transitionId);
|
||||||
|
|
||||||
|
await this.validateSingleEnd(options, transitionId);
|
||||||
|
|
||||||
|
await this.validateDefaultTransition(options, transitionId);
|
||||||
|
|
||||||
|
await this.validateDuplicateCondition(options, transitionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async validateSingleStart(
|
||||||
|
options: TransitionValidateOptions,
|
||||||
|
transitionId?: number,
|
||||||
|
) {
|
||||||
|
if (options.type !== QuestionTransitionType.START) return;
|
||||||
|
|
||||||
|
const qb = this.transitionsRepository
|
||||||
|
.createQueryBuilder('t')
|
||||||
|
.where('t.testId = :testId', {
|
||||||
|
testId: options.test.id,
|
||||||
|
})
|
||||||
|
.andWhere('t.type = :type', {
|
||||||
|
type: QuestionTransitionType.START,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (transitionId) {
|
||||||
|
qb.andWhere('t.id != :transitionId', {
|
||||||
|
transitionId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (await qb.getExists()) {
|
||||||
|
throw new AppException(
|
||||||
|
'questions.errors.questionTransition.startAlreadyExists',
|
||||||
|
HttpStatus.CONFLICT,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async validateSingleEnd(
|
||||||
|
options: TransitionValidateOptions,
|
||||||
|
transitionId?: number,
|
||||||
|
) {
|
||||||
|
if (options.type !== QuestionTransitionType.END) return;
|
||||||
|
|
||||||
|
const qb = this.transitionsRepository
|
||||||
|
.createQueryBuilder('t')
|
||||||
|
.where('t.fromQuestionId = :fromQuestionId', {
|
||||||
|
fromQuestionId: options.fromQuestion?.id,
|
||||||
|
})
|
||||||
|
.andWhere('t.type = :type', {
|
||||||
|
type: QuestionTransitionType.END,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (transitionId) {
|
||||||
|
qb.andWhere('t.id != :transitionId', {
|
||||||
|
transitionId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (await qb.getExists()) {
|
||||||
|
throw new AppException(
|
||||||
|
'questions.errors.questionTransition.endAlreadyExists',
|
||||||
|
HttpStatus.CONFLICT,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async validateDefaultTransition(
|
||||||
|
options: TransitionValidateOptions,
|
||||||
|
transitionId?: number,
|
||||||
|
) {
|
||||||
|
if (options.type !== QuestionTransitionType.DEFAULT) return;
|
||||||
|
|
||||||
|
const qb = this.transitionsRepository
|
||||||
|
.createQueryBuilder('t')
|
||||||
|
.where('t.fromQuestionId = :fromQuestionId', {
|
||||||
|
fromQuestionId: options.fromQuestion?.id,
|
||||||
|
})
|
||||||
|
.andWhere('t.type = :type', {
|
||||||
|
type: QuestionTransitionType.DEFAULT,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (transitionId) {
|
||||||
|
qb.andWhere('t.id != :transitionId', {
|
||||||
|
transitionId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (await qb.getExists()) {
|
||||||
|
throw new AppException(
|
||||||
|
'questions.errors.questionTransition.defaultAlreadyExists',
|
||||||
|
HttpStatus.CONFLICT,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async validateDuplicateCondition(
|
||||||
|
options: TransitionValidateOptions,
|
||||||
|
transitionId?: number,
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
options.type === QuestionTransitionType.DEFAULT ||
|
||||||
|
options.type === QuestionTransitionType.START ||
|
||||||
|
options.type === QuestionTransitionType.END
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const qb = this.transitionsRepository
|
||||||
|
.createQueryBuilder('t')
|
||||||
|
.where('t.fromQuestionId = :fromQuestionId', {
|
||||||
|
fromQuestionId: options.fromQuestion?.id,
|
||||||
|
})
|
||||||
|
.andWhere('t.type = :type', {
|
||||||
|
type: options.type,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (options.type === QuestionTransitionType.CHOICE) {
|
||||||
|
qb.andWhere(`t.conditionValue ->> 'choiceId' = :choiceId`, {
|
||||||
|
choiceId: String(
|
||||||
|
(options.conditionValue as SingleChoiceCondition).choiceId,
|
||||||
|
),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.type === QuestionTransitionType.NUMBER_RANGE) {
|
||||||
|
qb.andWhere(`t.conditionValue ->> 'min' = :min`, {
|
||||||
|
min: String((options.conditionValue as NumericCondition).min),
|
||||||
|
}).andWhere(`t.conditionValue ->> 'max' = :max`, {
|
||||||
|
max: String((options.conditionValue as NumericCondition).max),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transitionId) {
|
||||||
|
qb.andWhere('t.id != :transitionId', {
|
||||||
|
transitionId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (await qb.getExists()) {
|
||||||
|
throw new AppException(
|
||||||
|
'questions.errors.questionTransition.duplicateTransition',
|
||||||
|
HttpStatus.CONFLICT,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+20
-1
@@ -1,6 +1,6 @@
|
|||||||
import { HttpStatus, Injectable } from '@nestjs/common';
|
import { HttpStatus, Injectable } from '@nestjs/common';
|
||||||
import { InjectRepository } from '@nestjs/typeorm';
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
import { Repository } from 'typeorm';
|
import type { Repository } from 'typeorm';
|
||||||
import { TestsService } from '@/modules/tests/providers/tests.service';
|
import { TestsService } from '@/modules/tests/providers/tests.service';
|
||||||
import { QuestionTransition } from '../../../entities/question-transition.entity';
|
import { QuestionTransition } from '../../../entities/question-transition.entity';
|
||||||
import { Question } from '@/modules/questions/entities/question.entity';
|
import { Question } from '@/modules/questions/entities/question.entity';
|
||||||
@@ -13,16 +13,31 @@ import { AppException } from '@/common/exceptions/app.exception';
|
|||||||
import { QuestionsQueryProvider } from '../../questions-query.provider';
|
import { QuestionsQueryProvider } from '../../questions-query.provider';
|
||||||
import { TransitionValidateOptions } from '../../../interfaces/transition-validate-options.interface';
|
import { TransitionValidateOptions } from '../../../interfaces/transition-validate-options.interface';
|
||||||
import { QuestionTransitionTypeValidator } from '../../../validators/question-transition-type.validator';
|
import { QuestionTransitionTypeValidator } from '../../../validators/question-transition-type.validator';
|
||||||
|
import { CheckTransitionDBProvider } from './check-transition-db.provider';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class QuestionTransitionValidatorProvider {
|
export class QuestionTransitionValidatorProvider {
|
||||||
constructor(
|
constructor(
|
||||||
|
/**
|
||||||
|
* Inject Transitions Repository
|
||||||
|
*/
|
||||||
@InjectRepository(QuestionTransition)
|
@InjectRepository(QuestionTransition)
|
||||||
private readonly transitionsRepository: Repository<QuestionTransition>,
|
private readonly transitionsRepository: Repository<QuestionTransition>,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inject Tests Service
|
||||||
|
*/
|
||||||
private readonly testsService: TestsService,
|
private readonly testsService: TestsService,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inject Questions Query Provider
|
||||||
|
*/
|
||||||
private readonly questionsQueryProvider: QuestionsQueryProvider,
|
private readonly questionsQueryProvider: QuestionsQueryProvider,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inject CheckTransitionDB Provider
|
||||||
|
*/
|
||||||
|
private readonly checkTransitionDBProvider: CheckTransitionDBProvider,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public async validate(
|
public async validate(
|
||||||
@@ -120,6 +135,10 @@ export class QuestionTransitionValidatorProvider {
|
|||||||
};
|
};
|
||||||
|
|
||||||
QuestionTransitionTypeValidator.validateTransitionType(options);
|
QuestionTransitionTypeValidator.validateTransitionType(options);
|
||||||
|
|
||||||
|
await this.checkTransitionDBProvider.validate(options, transitionId);
|
||||||
|
|
||||||
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
private validateQuestions(
|
private validateQuestions(
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ import { QuestionRangeRuleService } from './providers/range-rule/question-range-
|
|||||||
import { QuestionRangeRuleCommandProvider } from './providers/range-rule/question-range-rule-command.provider';
|
import { QuestionRangeRuleCommandProvider } from './providers/range-rule/question-range-rule-command.provider';
|
||||||
import { QuestionRangeRuleQueryProvider } from './providers/range-rule/question-range-rule-query.provider';
|
import { QuestionRangeRuleQueryProvider } from './providers/range-rule/question-range-rule-query.provider';
|
||||||
import { QuestionTransition } from './entities/question-transition.entity';
|
import { QuestionTransition } from './entities/question-transition.entity';
|
||||||
|
import { CheckTransitionDBProvider } from './providers/transition/validations/check-transition-db.provider';
|
||||||
|
import { QuestionTransitionValidatorProvider } from './providers/transition/validations/question-transition-validator.provider';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -28,15 +30,24 @@ import { QuestionTransition } from './entities/question-transition.entity';
|
|||||||
],
|
],
|
||||||
controllers: [QuestionsController],
|
controllers: [QuestionsController],
|
||||||
providers: [
|
providers: [
|
||||||
|
// Questsions
|
||||||
QuestionsCommandProvider,
|
QuestionsCommandProvider,
|
||||||
QuestionsQueryProvider,
|
QuestionsQueryProvider,
|
||||||
QuestionsService,
|
QuestionsService,
|
||||||
|
|
||||||
|
// Choices
|
||||||
ChoicesCommandProvider,
|
ChoicesCommandProvider,
|
||||||
ChoicesQueryProvider,
|
ChoicesQueryProvider,
|
||||||
ChoicesService,
|
ChoicesService,
|
||||||
|
|
||||||
|
// Question Range Rules
|
||||||
QuestionRangeRuleCommandProvider,
|
QuestionRangeRuleCommandProvider,
|
||||||
QuestionRangeRuleQueryProvider,
|
QuestionRangeRuleQueryProvider,
|
||||||
QuestionRangeRuleService,
|
QuestionRangeRuleService,
|
||||||
|
|
||||||
|
// Question Transitions
|
||||||
|
CheckTransitionDBProvider,
|
||||||
|
QuestionTransitionValidatorProvider,
|
||||||
],
|
],
|
||||||
exports: [QuestionsService, ChoicesService, QuestionRangeRuleService],
|
exports: [QuestionsService, ChoicesService, QuestionRangeRuleService],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { NumericCondition } from '@/modules/questions/interfaces/numeric-conditi
|
|||||||
import { SingleChoiceCondition } from '@/modules/questions/interfaces/single-choice-condition.interface';
|
import { SingleChoiceCondition } from '@/modules/questions/interfaces/single-choice-condition.interface';
|
||||||
import { TransitionValidateOptions } from '@/modules/questions/interfaces/transition-validate-options.interface';
|
import { TransitionValidateOptions } from '@/modules/questions/interfaces/transition-validate-options.interface';
|
||||||
import { HttpStatus } from '@nestjs/common';
|
import { HttpStatus } from '@nestjs/common';
|
||||||
|
import { NumericMetadata } from '../interfaces/numeric-metadata.interface';
|
||||||
|
|
||||||
export class QuestionTransitionTypeValidator {
|
export class QuestionTransitionTypeValidator {
|
||||||
public static validateTransitionType(options: TransitionValidateOptions) {
|
public static validateTransitionType(options: TransitionValidateOptions) {
|
||||||
@@ -34,21 +35,21 @@ export class QuestionTransitionTypeValidator {
|
|||||||
private static validateStart(options: TransitionValidateOptions) {
|
private static validateStart(options: TransitionValidateOptions) {
|
||||||
if (options.fromQuestion) {
|
if (options.fromQuestion) {
|
||||||
throw new AppException(
|
throw new AppException(
|
||||||
'questionTransitions.errors.startMustNotHaveFromQuestion',
|
'questions.errors.questionTransition.startMustNotHaveFromQuestion',
|
||||||
HttpStatus.BAD_REQUEST,
|
HttpStatus.BAD_REQUEST,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!options.toQuestion) {
|
if (!options.toQuestion) {
|
||||||
throw new AppException(
|
throw new AppException(
|
||||||
'questionTransitions.errors.startMustHaveToQuestion',
|
'questions.errors.questionTransition.startMustHaveToQuestion',
|
||||||
HttpStatus.BAD_REQUEST,
|
HttpStatus.BAD_REQUEST,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.conditionValue) {
|
if (options.conditionValue) {
|
||||||
throw new AppException(
|
throw new AppException(
|
||||||
'questionTransitions.errors.startMustNotHaveCondition',
|
'questions.errors.questionTransition.startMustNotHaveCondition',
|
||||||
HttpStatus.BAD_REQUEST,
|
HttpStatus.BAD_REQUEST,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -57,21 +58,21 @@ export class QuestionTransitionTypeValidator {
|
|||||||
private static validateEnd(options: TransitionValidateOptions) {
|
private static validateEnd(options: TransitionValidateOptions) {
|
||||||
if (!options.fromQuestion) {
|
if (!options.fromQuestion) {
|
||||||
throw new AppException(
|
throw new AppException(
|
||||||
'questionTransitions.errors.endMustHaveFromQuestion',
|
'questions.errors.questionTransition.endMustHaveFromQuestion',
|
||||||
HttpStatus.BAD_REQUEST,
|
HttpStatus.BAD_REQUEST,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.toQuestion) {
|
if (options.toQuestion) {
|
||||||
throw new AppException(
|
throw new AppException(
|
||||||
'questionTransitions.errors.endMustNotHaveToQuestion',
|
'questions.errors.questionTransition.endMustNotHaveToQuestion',
|
||||||
HttpStatus.BAD_REQUEST,
|
HttpStatus.BAD_REQUEST,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.conditionValue) {
|
if (options.conditionValue) {
|
||||||
throw new AppException(
|
throw new AppException(
|
||||||
'questionTransitions.errors.endMustNotHaveCondition',
|
'questions.errors.questionTransition.endMustNotHaveCondition',
|
||||||
HttpStatus.BAD_REQUEST,
|
HttpStatus.BAD_REQUEST,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -80,14 +81,14 @@ export class QuestionTransitionTypeValidator {
|
|||||||
private static validateDefault(options: TransitionValidateOptions) {
|
private static validateDefault(options: TransitionValidateOptions) {
|
||||||
if (!options.fromQuestion || !options.toQuestion) {
|
if (!options.fromQuestion || !options.toQuestion) {
|
||||||
throw new AppException(
|
throw new AppException(
|
||||||
'questionTransitions.errors.invalidTransition',
|
'questions.errors.questionTransition.invalidTransition',
|
||||||
HttpStatus.BAD_REQUEST,
|
HttpStatus.BAD_REQUEST,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.conditionValue) {
|
if (options.conditionValue) {
|
||||||
throw new AppException(
|
throw new AppException(
|
||||||
'questionTransitions.errors.defaultMustNotHaveCondition',
|
'questions.errors.questionTransition.defaultMustNotHaveCondition',
|
||||||
HttpStatus.BAD_REQUEST,
|
HttpStatus.BAD_REQUEST,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -98,14 +99,14 @@ export class QuestionTransitionTypeValidator {
|
|||||||
|
|
||||||
if (!fromQuestion || !toQuestion) {
|
if (!fromQuestion || !toQuestion) {
|
||||||
throw new AppException(
|
throw new AppException(
|
||||||
'questionTransitions.errors.invalidTransition',
|
'questions.errors.questionTransition.invalidTransition',
|
||||||
HttpStatus.BAD_REQUEST,
|
HttpStatus.BAD_REQUEST,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fromQuestion.type !== QuestionType.MULTI_CHOICE) {
|
if (fromQuestion.type !== QuestionType.MULTI_CHOICE) {
|
||||||
throw new AppException(
|
throw new AppException(
|
||||||
'questionTransitions.errors.fromQuestionMustBeMultiChoice',
|
'questions.errors.questionTransition.fromQuestionMustBeMultiChoice',
|
||||||
HttpStatus.BAD_REQUEST,
|
HttpStatus.BAD_REQUEST,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -114,7 +115,7 @@ export class QuestionTransitionTypeValidator {
|
|||||||
|
|
||||||
if (typeof choiceId !== 'number') {
|
if (typeof choiceId !== 'number') {
|
||||||
throw new AppException(
|
throw new AppException(
|
||||||
'questionTransitions.errors.invalidChoiceCondition',
|
'questions.errors.questionTransition.invalidChoiceCondition',
|
||||||
HttpStatus.BAD_REQUEST,
|
HttpStatus.BAD_REQUEST,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -125,7 +126,7 @@ export class QuestionTransitionTypeValidator {
|
|||||||
|
|
||||||
if (!choiceExists) {
|
if (!choiceExists) {
|
||||||
throw new AppException(
|
throw new AppException(
|
||||||
'questionTransitions.errors.choiceNotBelongToQuestion',
|
'questions.errors.questionTransition.choiceNotBelongToQuestion',
|
||||||
HttpStatus.BAD_REQUEST,
|
HttpStatus.BAD_REQUEST,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -138,14 +139,14 @@ export class QuestionTransitionTypeValidator {
|
|||||||
|
|
||||||
if (!fromQuestion || !toQuestion) {
|
if (!fromQuestion || !toQuestion) {
|
||||||
throw new AppException(
|
throw new AppException(
|
||||||
'questionTransitions.errors.invalidTransition',
|
'questions.errors.questionTransition.invalidTransition',
|
||||||
HttpStatus.BAD_REQUEST,
|
HttpStatus.BAD_REQUEST,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fromQuestion.type !== QuestionType.NUMERIC) {
|
if (fromQuestion.type !== QuestionType.NUMERIC) {
|
||||||
throw new AppException(
|
throw new AppException(
|
||||||
'questionTransitions.errors.fromQuestionMustBeNumeric',
|
'questions.errors.questionTransition.fromQuestionMustBeNumeric',
|
||||||
HttpStatus.BAD_REQUEST,
|
HttpStatus.BAD_REQUEST,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -158,16 +159,27 @@ export class QuestionTransitionTypeValidator {
|
|||||||
typeof condition.max !== 'number'
|
typeof condition.max !== 'number'
|
||||||
) {
|
) {
|
||||||
throw new AppException(
|
throw new AppException(
|
||||||
'questionTransitions.errors.invalidNumberRange',
|
'questions.errors.questionTransition.invalidNumberRange',
|
||||||
HttpStatus.BAD_REQUEST,
|
HttpStatus.BAD_REQUEST,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (condition.min > condition.max) {
|
if (condition.min > condition.max) {
|
||||||
throw new AppException(
|
throw new AppException(
|
||||||
'questionTransitions.errors.invalidNumberRange',
|
'questions.errors.questionTransition.invalidNumberRange',
|
||||||
|
HttpStatus.BAD_REQUEST,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fromQuestion.metadata) {
|
||||||
|
const metadata = fromQuestion.metadata as NumericMetadata;
|
||||||
|
|
||||||
|
if (condition.min < metadata.min || condition.max > metadata.max) {
|
||||||
|
throw new AppException(
|
||||||
|
'questions.errors.questionTransition.invalidNumberRange',
|
||||||
HttpStatus.BAD_REQUEST,
|
HttpStatus.BAD_REQUEST,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user