From 4dc42aa6760eec2d10e88a987d079c0ebf4aa049 Mon Sep 17 00:00:00 2001 From: morteza-mortezai Date: Wed, 28 Jan 2026 16:33:30 +0330 Subject: [PATCH] print --- .../controller/form-builder.controller.ts | 34 +++++++------- .../form-builder/dto/create-field.dto.ts | 8 +++- .../form-builder/entities/field.entity.ts | 14 +++--- src/modules/form-builder/interface/print.ts | 5 +++ .../form-builder/provider/field.service.ts | 45 +++++++++++++------ .../print/controller/print.controller.ts | 6 +-- .../{section.entity.ts => print.entity.ts} | 6 +-- src/modules/print/print.module.ts | 16 +++---- .../{section.service.ts => Print.service.ts} | 18 ++++---- ...tion.repository.ts => print.repository.ts} | 6 +-- 10 files changed, 93 insertions(+), 65 deletions(-) rename src/modules/print/entities/{section.entity.ts => print.entity.ts} (70%) rename src/modules/print/provider/{section.service.ts => Print.service.ts} (73%) rename src/modules/print/repository/{section.repository.ts => print.repository.ts} (55%) diff --git a/src/modules/form-builder/controller/form-builder.controller.ts b/src/modules/form-builder/controller/form-builder.controller.ts index 5d75963..c5a33d4 100644 --- a/src/modules/form-builder/controller/form-builder.controller.ts +++ b/src/modules/form-builder/controller/form-builder.controller.ts @@ -10,7 +10,7 @@ import { UpdateFieldOptionDto } from '../dto/update-field-option.dto'; @Controller('admin') @ApiBearerAuth() - export class FormBuilderController { +export class FormBuilderController { constructor( private readonly fieldService: FieldService, private readonly fieldOptionService: FieldOptionService, @@ -19,36 +19,36 @@ import { UpdateFieldOptionDto } from '../dto/update-field-option.dto'; /*================================ Field ========================== */ - @Post('section/:id/field') - @ApiOperation({ summary: 'Create field for section' }) + @Post('entity/:id/field') + @ApiOperation({ summary: 'Create field for entity' }) @UseGuards(AdminAuthGuard) - createField(@Body() dto: CreateFieldDto, @Param('id') sectionId: string) { - return this.fieldService.create(sectionId,dto); + createField(@Body() dto: CreateFieldDto, @Param('id') entityId: string) { + return this.fieldService.create(+entityId, dto); } - @Get('section/:id/field') + @Get('entity/:id/field') @ApiOperation({ summary: 'find all secion fields' }) @UseGuards(AdminAuthGuard) - findAllSectionFields(@Param('id') sectionId: string) { - return this.fieldService.findAll(+sectionId); + findAllSectionFields(@Param('id') entityId: string) { + return this.fieldService.findAll(+entityId); } - @Get('section/field/:id') + @Get('entity/field/:id') @ApiOperation({ summary: 'Find one field' }) @UseGuards(AdminAuthGuard) findOneFiled(@Param('id') id: string) { return this.fieldService.findById(+id); } - @Patch('section/field/:id') + @Patch('entity/field/:id') @ApiOperation({ summary: 'Update field' }) @UseGuards(AdminAuthGuard) updateField(@Param('id') id: string, @Body() dto: UpdateFieldDto) { return this.fieldService.update(+id, dto); } - @Delete('section/field/:id') - @ApiOperation({ summary: 'Renopve field' }) + @Delete('entity/field/:id') + @ApiOperation({ summary: 'Remove field' }) @UseGuards(AdminAuthGuard) removeField(@Param('id') id: string) { return this.fieldService.remove(+id); @@ -56,35 +56,35 @@ import { UpdateFieldOptionDto } from '../dto/update-field-option.dto'; /*================================ Field Option ========================== */ - @Post('field/:id/option') + @Post('entity/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') + @Get('entity/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') + @Get('entity/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') + @Patch('entity/field/option/:id') @ApiOperation({ summary: 'Update field Option' }) @UseGuards(AdminAuthGuard) updateFieldOption(@Param('id') id: string, @Body() dto: UpdateFieldOptionDto) { return this.fieldOptionService.update(+id, dto); } - @Delete('field/option/:id') + @Delete('entity/field/option/:id') @ApiOperation({ summary: 'Renopve field Option' }) @UseGuards(AdminAuthGuard) removeFieldOption(@Param('id') id: string) { diff --git a/src/modules/form-builder/dto/create-field.dto.ts b/src/modules/form-builder/dto/create-field.dto.ts index 62f2285..9a38af9 100644 --- a/src/modules/form-builder/dto/create-field.dto.ts +++ b/src/modules/form-builder/dto/create-field.dto.ts @@ -1,7 +1,7 @@ import { IsString, IsOptional, IsBoolean, IsInt, Min, IsEnum, IsNotEmpty } from 'class-validator'; import { ApiPropertyOptional, ApiProperty } from '@nestjs/swagger'; import { Type } from 'class-transformer'; -import { FieldType } from '../interface/print'; +import { EntityType, FieldType } from '../interface/print'; export class CreateFieldDto { @IsString() @@ -23,6 +23,12 @@ export class CreateFieldDto { @ApiProperty({ enum: FieldType, example: FieldType.select }) type: FieldType; + @IsNotEmpty() + @IsEnum(EntityType) + @ApiProperty({ enum: EntityType, example: EntityType.product }) + entityType: EntityType + + @IsOptional() @IsInt() @Min(0) diff --git a/src/modules/form-builder/entities/field.entity.ts b/src/modules/form-builder/entities/field.entity.ts index 3665f64..4238c78 100644 --- a/src/modules/form-builder/entities/field.entity.ts +++ b/src/modules/form-builder/entities/field.entity.ts @@ -1,9 +1,7 @@ import { Collection, Entity, Enum, ManyToOne, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'; import { FieldOption } from './field-option.entity'; -import { FieldType } from '../interface/print'; -import { Section } from 'src/modules/print/entities/section.entity'; +import { EntityType, FieldType } from '../interface/print'; import { BaseEntity } from 'src/common/entities/base.entity'; -import { Product } from 'src/modules/product/entities/product.entity'; @Entity({ tableName: 'field' }) @@ -14,11 +12,13 @@ export class Field extends BaseEntity { @OneToMany(() => FieldOption, (attrValue) => attrValue.field) options = new Collection(this) - @ManyToOne(() => Section, { nullable: true }) - section?: Section + // Discriminator column + @Enum(() => EntityType) // Product , Print + entityType: EntityType; - @ManyToOne(() => Product, { nullable: true }) - product?: Product + // Foreign key based on entityType + @Property({ type: 'bigint' }) + entityId: bigint; @Property() name: string; diff --git a/src/modules/form-builder/interface/print.ts b/src/modules/form-builder/interface/print.ts index 5a34c25..6700f49 100644 --- a/src/modules/form-builder/interface/print.ts +++ b/src/modules/form-builder/interface/print.ts @@ -6,4 +6,9 @@ export enum FieldType { radio = 'radio', checkbox = 'checkbox', date = 'date', +} + +export enum EntityType { + product = 'product', + print = 'print', } \ No newline at end of file diff --git a/src/modules/form-builder/provider/field.service.ts b/src/modules/form-builder/provider/field.service.ts index 5927717..f413870 100644 --- a/src/modules/form-builder/provider/field.service.ts +++ b/src/modules/form-builder/provider/field.service.ts @@ -2,35 +2,52 @@ import { BadRequestException, Injectable, NotFoundException } from '@nestjs/comm import { EntityManager } from '@mikro-orm/postgresql'; import { RequiredEntityData } from '@mikro-orm/core'; import { FieldRepository } from '../repository/field.repository'; -import { SectionRepository } from 'src/modules/print/repository/section.repository'; +import { PrintRepository } from 'src/modules/print/repository/print.repository'; import { Field } from '../entities/field.entity'; import { CreateFieldDto } from '../dto/create-field.dto'; import { UpdateFieldDto } from '../dto/update-field.dto'; +import { ProductRepository } from 'src/modules/product/repositories/product.repository'; +import { EntityType } from '../interface/print'; +import { Product } from 'src/modules/product/entities/product.entity'; +import { Print } from 'src/modules/print/entities/print.entity'; +import { ProductService } from 'src/modules/product/providers/product.service'; +import { PrintService } from 'src/modules/print/provider/Print.service'; @Injectable() export class FieldService { constructor( - private readonly sectionRepository: SectionRepository, + private readonly sectionRepository: PrintRepository, private readonly fieldRepository: FieldRepository, + private readonly productService: ProductService, + private readonly printService: PrintService, private readonly em: EntityManager, ) { } - async create(sectionId: string, dto: CreateFieldDto) { - const section = await this.sectionRepository.findOne({ id: sectionId }) + async create(entityId: number, dto: CreateFieldDto) { + const { entityType, isRequired, multiple, name, type, order } = dto - if (!section) { - throw new BadRequestException("Section not found !") + let entity: null | Product | Print = null + + if (entityType == EntityType.product) { + entity = await this.productService.findOneOrFail(entityId) + } else if (entityType == EntityType.print) { + entity = await this.printService.findOneOrFail(entityId) + } + + if(!entity){ + throw new BadRequestException("Entity not Found") } const data: RequiredEntityData = { - name: dto.name, - order: dto.order, - type: dto.type, - section, - isRequired: dto.isRequired, - multiple: dto.multiple + name, + order, + type, + isRequired, + multiple, + entityId:entity.id, + entityType }; const field = this.fieldRepository.create(data) @@ -57,9 +74,9 @@ export class FieldService { } - findAll(sectionId: number) { + findAll(entityId: number) { return this.fieldRepository.find({ - section: { id: sectionId } + entityId }, { populate: ['options', 'options.value'] }); } diff --git a/src/modules/print/controller/print.controller.ts b/src/modules/print/controller/print.controller.ts index 0d132f3..084dcec 100644 --- a/src/modules/print/controller/print.controller.ts +++ b/src/modules/print/controller/print.controller.ts @@ -1,5 +1,5 @@ import { Controller, Get, Post, Body, Patch, Param, Delete, UseGuards } from '@nestjs/common'; -import { SectionService } from '../provider/section.service'; +import { PrintService } from '../provider/Print.service'; import { CreateSectionDto } from '../dto/create-section.dto'; import { ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; import { AdminAuthGuard } from '../../auth/guards/adminAuth.guard'; @@ -9,7 +9,7 @@ import { UpdateSectionDto } from '../dto/update-section.dto'; @ApiBearerAuth() export class PrintController { constructor( - private readonly sectionService: SectionService, + private readonly sectionService: PrintService, ) { } /*================================ Section ========================== */ @@ -32,7 +32,7 @@ export class PrintController { @ApiOperation({ summary: 'Find one section' }) @UseGuards(AdminAuthGuard) findOne(@Param('id') id: string) { - return this.sectionService.findById(+id); + return this.sectionService.findOneOrFail(+id); } @Patch('section/:id') diff --git a/src/modules/print/entities/section.entity.ts b/src/modules/print/entities/print.entity.ts similarity index 70% rename from src/modules/print/entities/section.entity.ts rename to src/modules/print/entities/print.entity.ts index 70a2184..7d64529 100644 --- a/src/modules/print/entities/section.entity.ts +++ b/src/modules/print/entities/print.entity.ts @@ -3,12 +3,12 @@ import { Field } from 'src/modules/form-builder/entities/field.entity'; import { BaseEntity } from 'src/common/entities/base.entity'; -@Entity({ tableName: 'section' }) -export class Section extends BaseEntity { +@Entity({ tableName: 'print' }) +export class Print extends BaseEntity { @PrimaryKey({ type: 'bigint', autoincrement: true }) id: bigint - @OneToMany(() => Field, (attrValue) => attrValue.section, { cascade: [Cascade.PERSIST, Cascade.REMOVE] }) + @OneToMany(() => Field, (attrValue) => attrValue.entityId, { cascade: [Cascade.PERSIST, Cascade.REMOVE] }) fields = new Collection(this) @Property() diff --git a/src/modules/print/print.module.ts b/src/modules/print/print.module.ts index 543061f..d4709fa 100644 --- a/src/modules/print/print.module.ts +++ b/src/modules/print/print.module.ts @@ -1,21 +1,21 @@ import { Module } from '@nestjs/common'; -import { SectionService } from './provider/section.service'; +import { PrintService } from './provider/Print.service'; import { PrintController } from './controller/print.controller'; import { MikroOrmModule } from '@mikro-orm/nestjs'; -import { Section } from './entities/section.entity'; +import { Print } from './entities/print.entity'; -import { SectionRepository } from './repository/section.repository'; +import { PrintRepository } from './repository/print.repository'; import { JwtModule } from '@nestjs/jwt'; import { RolesModule } from '../roles/roles.module'; @Module({ controllers: [PrintController], - providers: [SectionService, - SectionRepository], - exports: [SectionService, - SectionRepository], - imports: [MikroOrmModule.forFeature([Section]), + providers: [PrintService, + PrintRepository], + exports: [PrintService, + PrintRepository], + imports: [MikroOrmModule.forFeature([Print]), RolesModule, JwtModule.register({})] }) export class PrintModule { } diff --git a/src/modules/print/provider/section.service.ts b/src/modules/print/provider/Print.service.ts similarity index 73% rename from src/modules/print/provider/section.service.ts rename to src/modules/print/provider/Print.service.ts index 448847f..6ad2378 100644 --- a/src/modules/print/provider/section.service.ts +++ b/src/modules/print/provider/Print.service.ts @@ -1,23 +1,23 @@ import { Injectable, NotFoundException } from '@nestjs/common'; import { EntityManager } from '@mikro-orm/postgresql'; import { RequiredEntityData } from '@mikro-orm/core'; -import { SectionRepository } from '../repository/section.repository'; +import { PrintRepository } from '../repository/print.repository'; import { CreateSectionDto } from '../dto/create-section.dto'; -import { Section } from '../entities/section.entity'; +import { Print } from '../entities/print.entity'; import { UpdateSectionDto } from '../dto/update-section.dto'; @Injectable() -export class SectionService { +export class PrintService { constructor( - private readonly sectionRepository: SectionRepository, + private readonly sectionRepository: PrintRepository, private readonly em: EntityManager, ) { } async create(dto: CreateSectionDto) { - const data: RequiredEntityData
= { + const data: RequiredEntityData = { title: dto.title, order: dto.order, }; @@ -35,7 +35,7 @@ export class SectionService { const section = await this.sectionRepository.findOne({ id: sectionId }) if (!section) { - throw new NotFoundException('Section not found'); + throw new NotFoundException('Print not found'); } this.sectionRepository.assign(section, dto) @@ -50,16 +50,16 @@ export class SectionService { return this.sectionRepository.findAll({ populate: ['fields', 'fields.options', 'fields.options.value'] }); } - async findById(attributeId: number): Promise
{ + async findOneOrFail(attributeId: number): Promise { const section = await this.sectionRepository.findOne({ id: attributeId }, { populate: ['fields', 'fields.options', 'fields.options.value'] }); - if (!section) throw new NotFoundException('Section not found'); + if (!section) throw new NotFoundException('Print not found'); return section; } async remove(id: number): Promise { - const section = await this.findById(id); + const section = await this.findOneOrFail(id); section.deletedAt = new Date(); return await this.em.persistAndFlush(section); diff --git a/src/modules/print/repository/section.repository.ts b/src/modules/print/repository/print.repository.ts similarity index 55% rename from src/modules/print/repository/section.repository.ts rename to src/modules/print/repository/print.repository.ts index 7325991..231ba40 100644 --- a/src/modules/print/repository/section.repository.ts +++ b/src/modules/print/repository/print.repository.ts @@ -1,11 +1,11 @@ import { Injectable } from '@nestjs/common'; import { EntityManager, EntityRepository } from '@mikro-orm/postgresql'; -import { Section } from '../entities/section.entity'; +import { Print } from '../entities/print.entity'; @Injectable() -export class SectionRepository extends EntityRepository
{ +export class PrintRepository extends EntityRepository { constructor(readonly em: EntityManager) { - super(em, Section); + super(em, Print); } }