diff --git a/src/modules/print/print.controller.ts b/src/modules/print/controller/print.controller.ts similarity index 50% rename from src/modules/print/print.controller.ts rename to src/modules/print/controller/print.controller.ts index 9ef9f6c..f57e3cb 100644 --- a/src/modules/print/print.controller.ts +++ b/src/modules/print/controller/print.controller.ts @@ -1,11 +1,13 @@ import { Controller, Get, Post, Body, Patch, Param, Delete, UseGuards } from '@nestjs/common'; -import { SectionService } from './provider/section.service'; -import { CreateSectionDto } from './dto/create-section.dto'; -import { UpdateSectionDto } from './dto/update-section.dto'; +import { SectionService } from '../provider/section.service'; +import { CreateSectionDto } from '../dto/create-section.dto'; +import { UpdateSectionDto } from '../dto/update-section.dto'; import { ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; -import { AdminAuthGuard } from '../auth/guards/adminAuth.guard'; -import { FieldService } from './provider/field.service'; -import { CreateFieldDto } from './dto/create-field.dto'; +import { AdminAuthGuard } from '../../auth/guards/adminAuth.guard'; +import { FieldService } from '../provider/field.service'; +import { CreateFieldDto } from '../dto/create-field.dto'; +import { CreateFieldOptionDto } from '../dto/create-field-option.dto'; +import { FieldOptionService } from '../provider/field-option.service'; @Controller('admin/print') @ApiBearerAuth() @@ -14,6 +16,7 @@ export class PrintController { constructor( private readonly sectionService: SectionService, private readonly fieldService: FieldService, + private readonly fieldOptionService: FieldOptionService, ) { } /*================================ Section ========================== */ @@ -55,38 +58,75 @@ export class PrintController { /*================================ Field ========================== */ - @Post('field') - @ApiOperation({ summary: 'Create field' }) + @Post('section/:id/field') + @ApiOperation({ summary: 'Create field for section' }) @UseGuards(AdminAuthGuard) - createField(@Body() dto: CreateFieldDto) { - return this.fieldService.create(dto); + createField(@Body() dto: CreateFieldDto, @Param('id') sectionId: string) { + return this.fieldService.create(sectionId,dto); } - @Get('field') + @Get('section/field') @ApiOperation({ summary: 'find all field' }) @UseGuards(AdminAuthGuard) findAllFileds() { return this.sectionService.findAll(); } - @Get('field/:id') + @Get('section/field/:id') @ApiOperation({ summary: 'Find one field' }) @UseGuards(AdminAuthGuard) findOneFiled(@Param('id') id: string) { return this.sectionService.findById(+id); } - @Patch('field/:id') + @Patch('section/field/:id') @ApiOperation({ summary: 'Update field' }) @UseGuards(AdminAuthGuard) updateField(@Param('id') id: string, @Body() dto: UpdateSectionDto) { return this.sectionService.update(+id, dto); } - @Delete('field/:id') + @Delete('section/field/:id') @ApiOperation({ summary: 'Renopve field' }) @UseGuards(AdminAuthGuard) removeField(@Param('id') id: string) { return this.sectionService.remove(+id); } + + /*================================ Field ========================== */ + + @Post('field/:id/option') + @ApiOperation({ summary: 'Create field Options ' }) + @UseGuards(AdminAuthGuard) + createFieldOption(@Body() dto: CreateFieldOptionDto, @Param('id') id: string) { + return this.fieldOptionService.create(+id, dto); + } + + @Get('field/:id/option') + @ApiOperation({ summary: 'find all field Option' }) + @UseGuards(AdminAuthGuard) + findAllFiledOptions(@Param('id') fieldId: string) { + return this.fieldOptionService.findAll(+fieldId); + } + + @Get('field/option/:id') + @ApiOperation({ summary: 'Find one field Option' }) + @UseGuards(AdminAuthGuard) + findOneFiledOption(@Param('id') id: string) { + return this.fieldOptionService.findById(+id); + } + + @Patch('field/option/:id') + @ApiOperation({ summary: 'Update field Option' }) + @UseGuards(AdminAuthGuard) + updateFieldOption(@Param('id') id: string, @Body() dto: UpdateSectionDto) { + return this.fieldOptionService.update(+id, dto); + } + + @Delete('field/option/:id') + @ApiOperation({ summary: 'Renopve field Option' }) + @UseGuards(AdminAuthGuard) + removeFieldOption(@Param('id') id: string) { + return this.fieldOptionService.remove(+id); + } } diff --git a/src/modules/print/dto/create-field-option.dto.ts b/src/modules/print/dto/create-field-option.dto.ts new file mode 100644 index 0000000..8a70ddd --- /dev/null +++ b/src/modules/print/dto/create-field-option.dto.ts @@ -0,0 +1,16 @@ +import { IsString, IsOptional, IsInt, Min, IsNotEmpty } from 'class-validator'; +import { ApiPropertyOptional, ApiProperty } from '@nestjs/swagger'; +import { Type } from 'class-transformer'; + +export class CreateFieldOptionDto { + @IsString() + @ApiProperty() + value: string; + + @IsOptional() + @IsInt() + @Min(0) + @Type(() => Number) + @ApiPropertyOptional({ example: 1 }) + order?: number; +} diff --git a/src/modules/print/dto/create-field.dto.ts b/src/modules/print/dto/create-field.dto.ts index 2b105ce..62f2285 100644 --- a/src/modules/print/dto/create-field.dto.ts +++ b/src/modules/print/dto/create-field.dto.ts @@ -8,17 +8,16 @@ export class CreateFieldDto { @ApiProperty() name: string; - @IsString() - @IsNotEmpty() - @ApiProperty() - sectionId!: string; - - @IsBoolean() @Type(() => Boolean) @ApiPropertyOptional({ example: true }) isRequired: boolean; + @IsBoolean() + @Type(() => Boolean) + @ApiPropertyOptional({ example: true }) + multiple: boolean; + @IsNotEmpty() @IsEnum(FieldType) @ApiProperty({ enum: FieldType, example: FieldType.select }) diff --git a/src/modules/print/dto/update-field-option.dto.ts b/src/modules/print/dto/update-field-option.dto.ts new file mode 100644 index 0000000..06179f0 --- /dev/null +++ b/src/modules/print/dto/update-field-option.dto.ts @@ -0,0 +1,6 @@ +import { PartialType } from '@nestjs/swagger'; +import { CreateFieldOptionDto } from './create-field-option.dto'; + +export class UpdateFieldOptionDto extends PartialType(CreateFieldOptionDto) { + +} diff --git a/src/modules/print/entities/field.entity.ts b/src/modules/print/entities/field.entity.ts index 01d3e12..1902ae3 100644 --- a/src/modules/print/entities/field.entity.ts +++ b/src/modules/print/entities/field.entity.ts @@ -25,6 +25,9 @@ export class Field extends BaseEntity { @Property({ type: 'boolean', default: false }) isRequired: boolean = false; + @Property({ type: 'boolean', default: false }) + multiple: boolean = false; + @Property({ type: 'int', nullable: true }) order?: number; } diff --git a/src/modules/print/print.module.ts b/src/modules/print/print.module.ts index 1fd0b7c..c61f65a 100644 --- a/src/modules/print/print.module.ts +++ b/src/modules/print/print.module.ts @@ -1,6 +1,6 @@ import { Module } from '@nestjs/common'; import { SectionService } from './provider/section.service'; -import { PrintController } from './print.controller'; +import { PrintController } from './controller/print.controller'; import { MikroOrmModule } from '@mikro-orm/nestjs'; import { Field } from './entities/field.entity'; import { Section } from './entities/section.entity'; @@ -11,11 +11,15 @@ import { SectionRepository } from './repository/section.repository'; import { JwtModule } from '@nestjs/jwt'; import { RolesModule } from '../roles/roles.module'; import { FieldService } from './provider/field.service'; +import { FieldOptionService } from './provider/field-option.service'; @Module({ controllers: [PrintController], - providers: [SectionService, FieldRepository, FieldOptionRepository, SectionRepository,FieldService], - exports: [SectionService, FieldRepository, FieldOptionRepository, SectionRepository], - imports: [MikroOrmModule.forFeature([Field, Section, FieldOption]),RolesModule,JwtModule.register({})] + providers: [SectionService, FieldRepository, FieldOptionRepository, + SectionRepository, FieldService, FieldOptionService], + exports: [SectionService, FieldRepository, FieldOptionRepository, + SectionRepository, FieldOptionService], + imports: [MikroOrmModule.forFeature([Field, Section, FieldOption]), + RolesModule, JwtModule.register({})] }) export class PrintModule { } diff --git a/src/modules/print/provider/field-option.service.ts b/src/modules/print/provider/field-option.service.ts new file mode 100644 index 0000000..54d8f8c --- /dev/null +++ b/src/modules/print/provider/field-option.service.ts @@ -0,0 +1,78 @@ +import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common'; +import { EntityManager } from '@mikro-orm/postgresql'; +import { RequiredEntityData } from '@mikro-orm/core'; +import { FieldRepository } from '../repository/field.repository'; +import { FieldOption } from '../entities/field-option.entity'; +import { CreateFieldOptionDto } from '../dto/create-field-option.dto'; +import { FieldOptionRepository } from '../repository/field-option.repository'; +import { UpdateFieldOptionDto } from '../dto/update-field-option.dto'; + + +@Injectable() +export class FieldOptionService { + + constructor( + private readonly fieldOptionRepository: FieldOptionRepository, + private readonly fieldRepository: FieldRepository, + private readonly em: EntityManager, + ) { } + + async create(fieldId: number, dto: CreateFieldOptionDto) { + const field = await this.fieldRepository.findOne({ id: fieldId }) + + if (!field) { + throw new BadRequestException("filed not found !") + } + + const data: RequiredEntityData = { + order: dto.order, + value: dto.value, + field + }; + + const fieldOption = this.fieldOptionRepository.create(data) + + await this.em.persistAndFlush(fieldOption) + + return fieldOption + + } + + async update(fieldOptionId: number, dto: UpdateFieldOptionDto) { + + const fieldOption = await this.fieldOptionRepository.findOne({ id: fieldOptionId }) + + if (!fieldOption) { + throw new NotFoundException('fieldOption not found'); + } + + this.fieldOptionRepository.assign(fieldOption, dto) + + this.em.persistAndFlush(fieldOption) + + return fieldOption + + } + + findAll(fieldId: number) { + return this.fieldOptionRepository.find({ field: { id: fieldId } }); + } + + async findById(fieldOptionId: number): Promise { + const fieldOption = await this.fieldOptionRepository.findOne({ id: fieldOptionId }, + { populate: ['field'] }); + + if (!fieldOption) throw new NotFoundException('Field option not found'); + + return fieldOption; + } + + async remove(id: number): Promise { + const fieldOption = await this.findById(id); + + fieldOption.deletedAt = new Date(); + return await this.em.persistAndFlush(fieldOption); + + } + +} diff --git a/src/modules/print/provider/field.service.ts b/src/modules/print/provider/field.service.ts index 9be3865..91c65b8 100644 --- a/src/modules/print/provider/field.service.ts +++ b/src/modules/print/provider/field.service.ts @@ -17,8 +17,8 @@ export class FieldService { private readonly em: EntityManager, ) { } - async create(dto: CreateFieldDto) { - const section = await this.sectionRepository.findOne({ id: dto.sectionId }) + async create(sectionId: string, dto: CreateFieldDto) { + const section = await this.sectionRepository.findOne({ id: sectionId }) if (!section) { throw new BadRequestException("Section not found !") @@ -29,7 +29,8 @@ export class FieldService { order: dto.order, type: dto.type, section, - isRequired: dto.isRequired + isRequired: dto.isRequired, + multiple: dto.multiple }; const field = this.fieldRepository.create(data)