Skip to content
Merged
4 changes: 2 additions & 2 deletions src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { ProvaModule } from './modules/prova/prova.module';
import { QuestaoModule } from './modules/questao/questao.module';
import { SimuladoModule } from './modules/simulado/simulado.module';
import { SubjectModule } from './modules/questao/subject/subject.module';
import { TipoSimuladoModule } from './modules/tipo-simulado/tipo-simulado.module';
import { CategoriaModule } from './modules/categoria/categoria.module';
import { EnvModule } from './shared/modules/env/env.module';
import { Env, envSchema } from './shared/modules/env/env';

Expand All @@ -37,7 +37,7 @@ import { Env, envSchema } from './shared/modules/env/env';
FrenteModule,
MateriaModule,
QuestaoModule,
TipoSimuladoModule,
CategoriaModule,
SimuladoModule,
ProvaModule,
HistoricoModule,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,49 +10,49 @@ import {
import { ApiResponse, ApiTags } from '@nestjs/swagger';
import { GetAllDtoInput } from 'src/shared/dtos/get-all.dto.input';
import { GetAllDtoOutput } from 'src/shared/dtos/get-all.dto.output';
import { CreateTipoSimuladoDTOInput } from './dtos/create.dto.input';
import { TipoSimulado } from './schemas/tipo-simulado.schema';
import { TipoSimuladoService } from './tipo-simulado.service';
import { CreateCategoriaDTOInput } from './dtos/create.dto.input';
import { Categoria } from './schemas/categoria.schema';
import { CategoriaService } from './categoria.service';

@ApiTags('Tipo Simulado')
@Controller('v1/tipo-simulado')
export class TipoSimuladoController {
constructor(private readonly service: TipoSimuladoService) {}
@ApiTags('Categoria')
@Controller('v1/categoria')
export class CategoriaController {
constructor(private readonly service: CategoriaService) {}

@Get()
@ApiResponse({
status: 200,
description: 'materias cadastradas e validas',
type: TipoSimulado,
type: Categoria,
isArray: true,
})
public async getAll(
@Query() query: GetAllDtoInput,
): Promise<GetAllDtoOutput<TipoSimulado>> {
): Promise<GetAllDtoOutput<Categoria>> {
return await this.service.getAll(query);
}

@Post()
@ApiResponse({
status: 200,
description: 'cadastrado com sucesso',
type: TipoSimulado,
type: Categoria,
isArray: false,
})
public async post(
@Body() model: CreateTipoSimuladoDTOInput,
): Promise<TipoSimulado> {
@Body() model: CreateCategoriaDTOInput,
): Promise<Categoria> {
return await this.service.add(model);
}

@Get(':id')
@ApiResponse({
status: 200,
description: 'materias cadastradas e validas',
type: TipoSimulado,
type: Categoria,
isArray: false,
})
public async getById(@Param('id') id: string): Promise<TipoSimulado> {
public async getById(@Param('id') id: string): Promise<Categoria> {
return await this.service.getById(id);
}

Expand Down
35 changes: 35 additions & 0 deletions src/modules/categoria/categoria.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Module } from '@nestjs/common';
import { CategoriaService } from './categoria.service';
import { CategoriaController } from './categoria.controller';
import { CategoriaRepository } from './categoria.repository';
import { MongooseModule } from '@nestjs/mongoose';
import { Categoria, CategoriaSchema } from './schemas/categoria.schema';
import { CategoriaUniqueValidator } from './validator/categoria-unique.validator';
import { MateriaExistValidator } from '../materia/validator/materia-exist.validator';
import { FrenteExistValidator } from '../frente/validator/frente-exist.validator';
import { FrenteModule } from '../frente/frente.module';
import { MateriaModule } from '../materia/materia.module';
import { ExameModule } from '../exame/exame.module';
import { ExameExistValidator } from '../exame/validator/exame-exist.validator';

@Module({
imports: [
MongooseModule.forFeature([
{ name: Categoria.name, schema: CategoriaSchema },
]),
FrenteModule,
MateriaModule,
ExameModule,
],
controllers: [CategoriaController],
providers: [
CategoriaService,
CategoriaRepository,
CategoriaUniqueValidator,
MateriaExistValidator,
FrenteExistValidator,
ExameExistValidator,
],
exports: [CategoriaRepository],
})
export class CategoriaModule {}
33 changes: 33 additions & 0 deletions src/modules/categoria/categoria.repository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { BaseRepository } from 'src/shared/base/base.repository';
import { Categoria } from './schemas/categoria.schema';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { GetAllWhereInput } from 'src/shared/base/interfaces/get-all.input';
import { GetAllOutput } from 'src/shared/base/interfaces/get-all.output';

export class CategoriaRepository extends BaseRepository<Categoria> {
constructor(@InjectModel(Categoria.name) model: Model<Categoria>) {
super(model);
}

override async getById(id: string): Promise<Categoria> {
return await this.model
.findById(id)
.populate('exame');
}

override async getAll({
page,
limit,
where,
}: GetAllWhereInput): Promise<GetAllOutput<Categoria>> {
const data = await this.model
.find()
.skip((page - 1) * limit)
.limit(limit ?? Infinity)
.where({ ...where })
.populate('exame');
const totalItems = await this.model.where({ ...where }).countDocuments();
return { data, page, limit, totalItems };
}
}
28 changes: 28 additions & 0 deletions src/modules/categoria/categoria.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Injectable } from '@nestjs/common';
import { GetAllInput } from 'src/shared/base/interfaces/get-all.input';
import { GetAllOutput } from 'src/shared/base/interfaces/get-all.output';
import { CreateCategoriaDTOInput } from './dtos/create.dto.input';
import { Categoria } from './schemas/categoria.schema';
import { CategoriaRepository } from './categoria.repository';

@Injectable()
export class CategoriaService {
constructor(private readonly repository: CategoriaRepository) {}

public async add(item: CreateCategoriaDTOInput): Promise<Categoria> {
const categoria = Object.assign(new Categoria(), item);
return await this.repository.create(categoria);
}

public async getById(id: string): Promise<Categoria> {
return await this.repository.getById(id);
}

public async getAll(param: GetAllInput): Promise<GetAllOutput<Categoria>> {
return await this.repository.getAll(param);
}

public async delete(id: string): Promise<void> {
await this.repository.delete(id);
}
}
46 changes: 46 additions & 0 deletions src/modules/categoria/dtos/create.dto.input.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { ApiProperty } from '@nestjs/swagger';
import {
IsBoolean,
IsMongoId,
IsNumber,
IsOptional,
IsString,
} from 'class-validator';
import { CategoriaUnique } from '../validator/categoria-unique.validator';
import { ExameExist } from '../../exame/validator/exame-exist.validator';

export class CreateCategoriaDTOInput {
@ApiProperty()
@IsString()
@CategoriaUnique({ message: 'nome categoria já existe' })
public nome: string;

@ApiProperty()
@IsNumber()
public duracao: number;

@ApiProperty({ required: false })
@IsNumber()
@IsOptional()
public quantidadeTotalQuestao: number;

@ApiProperty()
@IsMongoId()
@ExameExist({ message: 'exame não encontrado' })
public exame: string;

@ApiProperty({ required: false, default: false })
@IsBoolean()
@IsOptional()
public custom: boolean;

@ApiProperty({ required: false, default: true })
@IsBoolean()
@IsOptional()
public selecionavel: boolean;

@ApiProperty({ required: false, default: '' })
@IsString()
@IsOptional()
public descricao: string;
}
38 changes: 38 additions & 0 deletions src/modules/categoria/schemas/categoria.schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { BaseSchema } from 'src/shared/base/base.schema';
import { ApiProperty } from '@nestjs/swagger';
import { Types } from 'mongoose';
import { Exame } from '../../exame/exame.schema';

@Schema({ timestamps: true, versionKey: false })
export class Categoria extends BaseSchema {
@Prop({ unique: true })
@ApiProperty()
public nome: string;

@Prop()
@ApiProperty()
public duracao: number;

@Prop({ required: false, default: null })
@ApiProperty({ required: false, nullable: true })
public quantidadeTotalQuestao: number | null;

@Prop({ ref: Exame.name, type: Types.ObjectId, required: true })
@ApiProperty()
public exame: Exame;

@Prop({ required: true, default: false })
@ApiProperty({ default: false })
public custom: boolean;

@Prop({ required: true, default: true })
@ApiProperty({ default: true })
public selecionavel: boolean;

@Prop({ required: false, default: '' })
@ApiProperty({ required: false, default: '' })
public descricao: string;
}

export const CategoriaSchema = SchemaFactory.createForClass(Categoria);
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,33 @@ import {
ValidatorConstraintInterface,
registerDecorator,
} from 'class-validator';
import { TipoSimuladoRepository } from '../tipo-simulado.repository';
import { CategoriaRepository } from '../categoria.repository';

@Injectable()
@ValidatorConstraint({ async: true })
export class TipoSimuladoExistValidator
implements ValidatorConstraintInterface
{
export class CategoriaExistValidator implements ValidatorConstraintInterface {
constructor(
private readonly tipoSimuladoRepository: TipoSimuladoRepository,
private readonly categoriaRepository: CategoriaRepository,
) {}

async validate(value: any): Promise<boolean> {
try {
const tipoSimulado = await this.tipoSimuladoRepository.getById(value);
return !!tipoSimulado;
const categoria = await this.categoriaRepository.getById(value);
return !!categoria;
} catch {
return false;
}
}
}

export const TipoSimuladoExist = (validationOptions: ValidationOptions) => {
export const CategoriaExist = (validationOptions: ValidationOptions) => {
return (obj: object, props: string) => {
registerDecorator({
target: obj.constructor,
propertyName: props,
options: validationOptions,
constraints: [],
validator: TipoSimuladoExistValidator,
validator: CategoriaExistValidator,
});
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,31 @@ import {
ValidatorConstraintInterface,
registerDecorator,
} from 'class-validator';
import { TipoSimuladoRepository } from '../tipo-simulado.repository';
import { CategoriaRepository } from '../categoria.repository';

@Injectable()
@ValidatorConstraint({ async: true })
export class TipoSimuladoUniqueValidator
implements ValidatorConstraintInterface
{
export class CategoriaUniqueValidator implements ValidatorConstraintInterface {
constructor(
private readonly tipoSimuladoRepository: TipoSimuladoRepository,
private readonly categoriaRepository: CategoriaRepository,
) {}

async validate(value: any): Promise<boolean> {
const tipoSimulado = await this.tipoSimuladoRepository.getByFilter({
const categoria = await this.categoriaRepository.getByFilter({
nome: value,
});
return !tipoSimulado;
return !categoria;
}
}

export const TipoSimuladoUnique = (validationOptions: ValidationOptions) => {
export const CategoriaUnique = (validationOptions: ValidationOptions) => {
return (obj: object, props: string) => {
registerDecorator({
target: obj.constructor,
propertyName: props,
options: validationOptions,
constraints: [],
validator: TipoSimuladoUniqueValidator,
validator: CategoriaUniqueValidator,
});
};
};
20 changes: 20 additions & 0 deletions src/modules/exame/exame-seed.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Injectable, OnModuleInit } from '@nestjs/common';
import { ExameRepository } from './exame.repository';
import { Exame } from './exame.schema';
import { Localizacao } from './enum/localizacao.enum';

@Injectable()
export class ExameSeedService implements OnModuleInit {
constructor(private readonly repo: ExameRepository) {}

async onModuleInit() {
const exists = await this.repo.getByFilter({ nome: 'Personalizado' });
if (!exists) {
const exame = Object.assign(new Exame(), {
nome: 'Personalizado',
localizacao: Localizacao.BR,
});
await this.repo.create(exame);
}
}
}
2 changes: 2 additions & 0 deletions src/modules/exame/exame.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { MongooseModule } from '@nestjs/mongoose';
import { ExameSchema } from './exame.schema';
import { ExameUniqueValidator } from './validator/exame-unique.validator';
import { ExameExistValidator } from './validator/exame-exist.validator';
import { ExameSeedService } from './exame-seed.service';

@Module({
imports: [
Expand All @@ -17,6 +18,7 @@ import { ExameExistValidator } from './validator/exame-exist.validator';
ExameRepository,
ExameUniqueValidator,
ExameExistValidator,
ExameSeedService,
],
exports: [ExameService, ExameRepository],
})
Expand Down
Loading
Loading