diff --git a/src/app.module.ts b/src/app.module.ts index 0ece03d..ef756a0 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -9,6 +9,7 @@ import { AuthModule } from './auth/auth.module'; import { OrganModule } from './organ/organ.module'; import { ComplaintModule } from './complaint/complaint.module'; import { AttachmentModule } from './attachment/attachment.module'; +import { ReplyModule } from './reply/reply.module'; @Module({ imports: [ @@ -22,7 +23,8 @@ import { AttachmentModule } from './attachment/attachment.module'; AuthModule, OrganModule, ComplaintModule, - AttachmentModule + AttachmentModule, + ReplyModule ], }) export class AppModule {} diff --git a/src/attachment/entities/attachment.entity.ts b/src/attachment/entities/attachment.entity.ts index 7df7e46..5120678 100644 --- a/src/attachment/entities/attachment.entity.ts +++ b/src/attachment/entities/attachment.entity.ts @@ -2,6 +2,7 @@ import { BaseEntity } from "src/common/entities/base.entity"; import { Column, Entity, OneToOne } from "typeorm"; import { AttachmentType } from "../enums/attachment-type.enum"; import { ComplaintAttachment } from "src/complaint/entities/complaint-attachment.entity"; +import { ReplyAttachment } from "src/reply/entities/reply-attachment.entity"; @Entity('attachments') export class Attachment extends BaseEntity{ @@ -24,4 +25,7 @@ export class Attachment extends BaseEntity{ @OneToOne(() => ComplaintAttachment, (ca) => ca.attachment) complaint: ComplaintAttachment; + + @OneToOne(() => ReplyAttachment, (ra) => ra.attachment) + reply: ReplyAttachment; } diff --git a/src/common/enums/messages.enum.ts b/src/common/enums/messages.enum.ts index b11c09e..63147cf 100644 --- a/src/common/enums/messages.enum.ts +++ b/src/common/enums/messages.enum.ts @@ -30,4 +30,8 @@ export enum ComplaintMessages { export enum AttachmentMessages { ATTACHMENT_NOT_FOUND = 'ضمیمه مورد نظر پیدا نشد!' +} + +export enum ReplyMessages { + REPLY_NOT_FOUND = 'پاسخ مورد نظر پیدا نشد!' } \ No newline at end of file diff --git a/src/complaint/entities/complaint.entity.ts b/src/complaint/entities/complaint.entity.ts index 8ca0315..228c3fd 100644 --- a/src/complaint/entities/complaint.entity.ts +++ b/src/complaint/entities/complaint.entity.ts @@ -4,6 +4,7 @@ import { User } from 'src/users/entities/user.entity'; import { Organ } from 'src/organ/entities/organ.entity'; import { BaseEntity } from 'src/common/entities/base.entity'; import { ComplaintAttachment } from './complaint-attachment.entity'; +import { Reply } from 'src/reply/entities/reply.entity'; @Entity('complaints') export class Complaint extends BaseEntity { @@ -45,4 +46,7 @@ export class Complaint extends BaseEntity { @OneToMany(() => ComplaintAttachment, (ca) => ca.complaint) attachments: ComplaintAttachment[]; + + @OneToMany(() => Reply, (reply) => reply.complaint) + messages: Reply[]; } diff --git a/src/reply/dto/create-reply.dto.ts b/src/reply/dto/create-reply.dto.ts new file mode 100644 index 0000000..1d73c38 --- /dev/null +++ b/src/reply/dto/create-reply.dto.ts @@ -0,0 +1,32 @@ +import { ApiProperty } from "@nestjs/swagger"; +import { IsNotEmpty, IsString, IsUUID } from "class-validator"; + +export class CreateReplyDto { + @ApiProperty({ + description: 'text content of the reply' + }) + @IsString() + @IsNotEmpty() + content: string; + + @ApiProperty({ + description: 'Id of the sender user' + }) + @IsNotEmpty() + @IsUUID() + senderId: string; + + @ApiProperty({ + description: 'Id of the receiver user' + }) + @IsNotEmpty() + @IsUUID() + receiverId: string; + + @ApiProperty({ + description: 'Id of the Complaint' + }) + @IsNotEmpty() + @IsUUID() + complaintId: string; +} diff --git a/src/reply/dto/update-reply.dto.ts b/src/reply/dto/update-reply.dto.ts new file mode 100644 index 0000000..7ace067 --- /dev/null +++ b/src/reply/dto/update-reply.dto.ts @@ -0,0 +1,4 @@ +import { PartialType } from '@nestjs/swagger'; +import { CreateReplyDto } from './create-reply.dto'; + +export class UpdateReplyDto extends PartialType(CreateReplyDto) {} diff --git a/src/reply/entities/reply-attachment.entity.ts b/src/reply/entities/reply-attachment.entity.ts new file mode 100644 index 0000000..43a9b91 --- /dev/null +++ b/src/reply/entities/reply-attachment.entity.ts @@ -0,0 +1,19 @@ +import { BaseEntity } from "src/common/entities/base.entity"; +import { Column, Entity, JoinColumn, ManyToOne, OneToOne } from "typeorm"; +import { Reply } from "./reply.entity"; +import { Attachment } from "src/attachment/entities/attachment.entity"; + +@Entity('reply_attachments') +export class ReplyAttachment extends BaseEntity { + @ManyToOne(() => Reply, (rp) => rp.attachments, { + onDelete: 'CASCADE' + }) + reply: Reply; + + @OneToOne(() => Attachment, (attch) => attch.reply, { + cascade: true, + onDelete: 'CASCADE' + }) + @JoinColumn() + attachment: Attachment; +} \ No newline at end of file diff --git a/src/reply/entities/reply.entity.ts b/src/reply/entities/reply.entity.ts new file mode 100644 index 0000000..9c362ce --- /dev/null +++ b/src/reply/entities/reply.entity.ts @@ -0,0 +1,26 @@ +import { Attachment } from "src/attachment/entities/attachment.entity"; +import { BaseEntity } from "src/common/entities/base.entity"; +import { Complaint } from "src/complaint/entities/complaint.entity"; +import { User } from "src/users/entities/user.entity"; +import { Column, Entity, ManyToOne, OneToMany } from "typeorm"; +import { ReplyAttachment } from "./reply-attachment.entity"; + +@Entity('replies') +export class Reply extends BaseEntity { + @Column({ + type: 'text' + }) + content: string; // the text or message written. + + @ManyToOne(() => User) + sender: User; + + @ManyToOne(() => User) + receiver: User; + + @ManyToOne(() => Complaint, (complaint) => complaint.messages) + complaint: Complaint; + + @OneToMany(() => ReplyAttachment, (ra) => ra.reply) + attachments: ReplyAttachment; +} diff --git a/src/reply/reply.controller.ts b/src/reply/reply.controller.ts new file mode 100644 index 0000000..687547f --- /dev/null +++ b/src/reply/reply.controller.ts @@ -0,0 +1,34 @@ +import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common'; +import { ReplyService } from './reply.service'; +import { CreateReplyDto } from './dto/create-reply.dto'; +import { UpdateReplyDto } from './dto/update-reply.dto'; + +@Controller('reply') +export class ReplyController { + constructor(private readonly replyService: ReplyService) {} + + @Post() + create(@Body() createReplyDto: CreateReplyDto) { + return this.replyService.create(createReplyDto); + } + + @Get() + findAll() { + return this.replyService.findAll(); + } + + @Get(':id') + findOne(@Param('id') id: string) { + return this.replyService.findOneOrFail(id); + } + + @Patch(':id') + update(@Param('id') id: string, @Body() updateReplyDto: UpdateReplyDto) { + return this.replyService.update(id, updateReplyDto); + } + + @Delete(':id') + remove(@Param('id') id: string) { + return this.replyService.remove(id); + } +} diff --git a/src/reply/reply.module.ts b/src/reply/reply.module.ts new file mode 100644 index 0000000..5c884d4 --- /dev/null +++ b/src/reply/reply.module.ts @@ -0,0 +1,15 @@ +import { Module } from '@nestjs/common'; +import { ReplyService } from './reply.service'; +import { ReplyController } from './reply.controller'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { Reply } from './entities/reply.entity'; +import { ReplyAttachment } from './entities/reply-attachment.entity'; +import { ReplyRepository } from './repositories/reply.repository'; +import { ReplyAttachmentRepository } from './repositories/reply-attachment.repository'; + +@Module({ + imports: [TypeOrmModule.forFeature([Reply, ReplyAttachment])], + controllers: [ReplyController], + providers: [ReplyService, ReplyRepository, ReplyAttachmentRepository], +}) +export class ReplyModule {} diff --git a/src/reply/reply.service.ts b/src/reply/reply.service.ts new file mode 100644 index 0000000..f60422d --- /dev/null +++ b/src/reply/reply.service.ts @@ -0,0 +1,44 @@ +import { Injectable, NotFoundException } from '@nestjs/common'; +import { CreateReplyDto } from './dto/create-reply.dto'; +import { UpdateReplyDto } from './dto/update-reply.dto'; +import { ReplyRepository } from './repositories/reply.repository'; +// import { ReplyAttachmentRepository } from './repositories/reply-attachment.repository'; +import { Reply } from './entities/reply.entity'; +import { ReplyMessages } from 'src/common/enums/messages.enum'; + +@Injectable() +export class ReplyService { + constructor( + private readonly replyRepository: ReplyRepository, + // private readonly replyAttachmentRepository: ReplyAttachmentRepository, + ) {} + + async create(createReplyDto: CreateReplyDto): Promise { + const reply = this.replyRepository.create(createReplyDto); + await this.replyRepository.save(reply); + return reply; + } + + async findAll(): Promise { + return await this.replyRepository.find(); + } + + async findOneOrFail(id: string): Promise { + const reply = await this.replyRepository.findOne({where: {id}}); + if(!reply) throw new NotFoundException(ReplyMessages.REPLY_NOT_FOUND); + + return reply; + } + + async update(id: string, updateReplyDto: UpdateReplyDto): Promise { + const reply = await this.findOneOrFail(id); + Object.assign(reply, updateReplyDto); + return reply; + } + + async remove(id: string): Promise { + const reply = await this.findOneOrFail(id); + await this.replyRepository.remove(reply); + return reply; + } +} diff --git a/src/reply/repositories/reply-attachment.repository.ts b/src/reply/repositories/reply-attachment.repository.ts new file mode 100644 index 0000000..dccfee0 --- /dev/null +++ b/src/reply/repositories/reply-attachment.repository.ts @@ -0,0 +1,11 @@ +import { Injectable } from "@nestjs/common"; +import { Repository } from "typeorm"; +import { ReplyAttachment } from "../entities/reply-attachment.entity"; +import { InjectRepository } from "@nestjs/typeorm"; + +@Injectable() +export class ReplyAttachmentRepository extends Repository { + constructor(@InjectRepository(ReplyAttachment) replyAttachmentRepository: Repository) { + super(replyAttachmentRepository.target, replyAttachmentRepository.manager, replyAttachmentRepository.queryRunner); + } +} \ No newline at end of file diff --git a/src/reply/repositories/reply.repository.ts b/src/reply/repositories/reply.repository.ts new file mode 100644 index 0000000..e59f558 --- /dev/null +++ b/src/reply/repositories/reply.repository.ts @@ -0,0 +1,11 @@ +import { Repository } from "typeorm"; +import { Reply } from "../entities/reply.entity"; +import { InjectRepository } from "@nestjs/typeorm"; +import { Injectable } from "@nestjs/common"; + +@Injectable() +export class ReplyRepository extends Repository { + constructor(@InjectRepository(Reply) replyRepository: Repository) { + super(replyRepository.target, replyRepository.manager, replyRepository.queryRunner); + } +} \ No newline at end of file