feat: added reply section

This commit is contained in:
2026-07-28 20:06:15 +03:30
parent 823d43fc75
commit e462606416
13 changed files with 211 additions and 1 deletions
+3 -1
View File
@@ -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 {}
@@ -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;
}
+4
View File
@@ -30,4 +30,8 @@ export enum ComplaintMessages {
export enum AttachmentMessages {
ATTACHMENT_NOT_FOUND = 'ضمیمه مورد نظر پیدا نشد!'
}
export enum ReplyMessages {
REPLY_NOT_FOUND = 'پاسخ مورد نظر پیدا نشد!'
}
@@ -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[];
}
+32
View File
@@ -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;
}
+4
View File
@@ -0,0 +1,4 @@
import { PartialType } from '@nestjs/swagger';
import { CreateReplyDto } from './create-reply.dto';
export class UpdateReplyDto extends PartialType(CreateReplyDto) {}
@@ -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;
}
+26
View File
@@ -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;
}
+34
View File
@@ -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);
}
}
+15
View File
@@ -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 {}
+44
View File
@@ -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<Reply> {
const reply = this.replyRepository.create(createReplyDto);
await this.replyRepository.save(reply);
return reply;
}
async findAll(): Promise<Reply[]> {
return await this.replyRepository.find();
}
async findOneOrFail(id: string): Promise<Reply> {
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<Reply> {
const reply = await this.findOneOrFail(id);
Object.assign(reply, updateReplyDto);
return reply;
}
async remove(id: string): Promise<Reply> {
const reply = await this.findOneOrFail(id);
await this.replyRepository.remove(reply);
return reply;
}
}
@@ -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<ReplyAttachment> {
constructor(@InjectRepository(ReplyAttachment) replyAttachmentRepository: Repository<ReplyAttachment>) {
super(replyAttachmentRepository.target, replyAttachmentRepository.manager, replyAttachmentRepository.queryRunner);
}
}
@@ -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<Reply> {
constructor(@InjectRepository(Reply) replyRepository: Repository<Reply>) {
super(replyRepository.target, replyRepository.manager, replyRepository.queryRunner);
}
}